5.7、配置


5.7.1 获取并设置配置

var builder = new ConfigurationBuilder();
builder.AddInMemoryCollection();
var config = builder.Build();
config["somekey"] = "somevalue";
// do some other work
var setting = config["somekey"]; // also returns "somevalue"

5.7.2 使用内置源

如果一个字符串存在于多个配置文件中。最后一个配置源将被使用。ASP.NET团队建议最后指定环境变量,以便本地环境可以覆盖部署中设置的任何配置文件。

  • 环境指定的配置文件。

    public Startup(IHostingEnvironment env)
    {
      var builder = new ConfigurationBuilder()
      .SetBasePath(env.ContentRootPath)
      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
      if (env.IsDevelopment())
      {
          // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=builder.AddUserSecrets();
      }
      builder.AddEnvironmentVariables();
      Configuration = builder.Build();
    }
    

    在开发环境中,上面代码将查找名为appsettings.Development.json的文件并使用它的值。您不应该在configuration provider或纯文本中存储密码或其他敏感数据。 您也不应在开发或测试环境中使用生产秘密。相反,这样的秘密应该在项目之外指定。

  • +++ 指定默认值

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.Extensions.Configuration;
    namespace ConfigConsole
    {
      public static class Program
      {
          public static void Main(string[] args)
          {
              var builder = new ConfigurationBuilder();
              Console.WriteLine("Initial Config Sources: " + builder.Sources.Count());
              builder.AddInMemoryCollection(new Dictionary<string, string>
              {
                  { "username", "Guest" }
              });
              Console.WriteLine("Added Memory Source. Sources: " + builder.Sources.Count());
              builder.AddCommandLine(args);
              Console.WriteLine("Added Command Line Source. Sources: " + builder.Sources.Count());
              var config = builder.Build();
              string username = config["username"];
              Console.WriteLine($"Hello, {username}!");
          }
      }
    }
    

5.7.3 使用Options对象和configuration对象

  • IOptions<TOptions>

    public class MyOptions
    {
      public string Option1 { get; set; }
      public int Option2 { get; set; }
    }
    
    public class HomeController : Controller
    {
      private readonly IOptions<MyOptions> _optionsAccessor;
      public HomeController(IOptions<MyOptions> optionsAccessor)
      {
          _optionsAccessor = optionsAccessor;
      }
      // GET: /<controller>/
      public IActionResult Index() => View(_optionsAccessor.Value);
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
      // Setup options with DI
      services.AddOptions();
    }
    
  • 使用delegate或者是绑定options到configuration

    public void ConfigureServices(IServiceCollection services)
    {
      // Setup options with DI
      services.AddOptions();
      // Configure MyOptions using config by installing Microsoft.Extensions.Options.ConfigurationExtensions
      services.Configure<MyOptions>(Configuration);
      // Configure MyOptions using code
      services.Configure<MyOptions>(myOptions =>
      {
          myOptions.Option1 = "value1_from_action";
      });
      // Configure MySubOptions using a sub-section of the appsettings.json file
      services.Configure<MySubOptions>(Configuration.GetSection("subsection"));
      // Add framework services.
      services.AddMvc();
    }
    

    每次调用Configure <TOptions>会将IConfigureOptions <TOptions>服务添加到IOptions <TOptions>服务使用的服务容器中,以提供configured options到应用程序或框架。 如果要使用对象来配置Option,那么对象必须从服务容器中获取(例如,从数据库中读取设置)使用 AddSingleton<IConfigureOptions<TOptions>> 扩展方法注册自定义 IConfigureOptions<TOptions>服务。

5.7.4 编写自定义providers

  • 举例:Entity Framework Settings

    public class ConfigurationValue
    {
      public string Id { get; set; }
      public string Value { get; set; }
    }
    
    public class ConfigurationContext : DbContext
    {
      public ConfigurationContext(DbContextOptions options) : base(options)
      {
      }
      public DbSet<ConfigurationValue> Values { get; set; }
    }
    
    using System;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    namespace CustomConfigurationProvider
    {
      public class EntityFrameworkConfigurationSource : IConfigurationSource
      {
          private readonly Action<DbContextOptionsBuilder> _optionsAction;
          public EntityFrameworkConfigurationSource(Action<DbContextOptionsBuilder> optionsAction)
          {
              _optionsAction = optionsAction;
          }
          public IConfigurationProvider Build(IConfigurationBuilder builder)
          {
              return new EntityFrameworkConfigurationProvider(_optionsAction);
          }
      }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    namespace CustomConfigurationProvider
    {
      public class EntityFrameworkConfigurationProvider : ConfigurationProvider
      {
          public EntityFrameworkConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
          {
              OptionsAction = optionsAction;
          }
          Action<DbContextOptionsBuilder> OptionsAction { get; }
          public override void Load()
          {
              var builder = new DbContextOptionsBuilder<ConfigurationContext>();
              OptionsAction(builder);
              using (var dbContext = new ConfigurationContext(builder.Options))
              {
                  dbContext.Database.EnsureCreated();
                  Data = !dbContext.Values.Any()
                  ? CreateAndSaveDefaultValues(dbContext)
                  : dbContext.Values.ToDictionary(c => c.Id, c => c.Value);
              }
          }
          private static IDictionary<string, string> CreateAndSaveDefaultValues(
          ConfigurationContext dbContext)
          {
              var configValues = new Dictionary<string, string>
              {
                  { "key1", "value_from_ef_1" },
                  { "key2", "value_from_ef_2" }
              };
              dbContext.Values.AddRange(configValues
              .Select(kvp => new ConfigurationValue { Id = kvp.Key, Value = kvp.Value })
              .ToArray());
              dbContext.SaveChanges();
              return configValues;
          }
      }
    }
    
  • AddEntityFrameworkConfiguration

    using System;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    namespace CustomConfigurationProvider
    {
      public static class EntityFrameworkExtensions
      {
          public static IConfigurationBuilder AddEntityFrameworkConfig(
          this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> setup)
          {
              return builder.Add(new EntityFrameworkConfigurationSource(setup));
          }
      }
    }
    
    using System;
    using System.IO;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    namespace CustomConfigurationProvider
    {
      public static class Program
      {
          public static void Main()
          {
              // work with with a builder using multiple calls
              var builder = new ConfigurationBuilder();
              builder.SetBasePath(Directory.GetCurrentDirectory());
              builder.AddJsonFile("appsettings.json");
              var connectionStringConfig = builder.Build();
              // chain calls together as a fluent API
              var config = new ConfigurationBuilder()
              .SetBasePath(Directory.GetCurrentDirectory())
              .AddJsonFile("appsettings.json")
              .AddEntityFrameworkConfig(options =>
              options.UseSqlServer(connectionStringConfig.GetConnectionString("DefaultConnection"))).Build();
              Console.WriteLine("key1={0}", config["key1"]);
              Console.WriteLine("key2={0}", config["key2"]);
              Console.WriteLine("key3={0}", config["key3"]);
          }
      }
    }
    

    5.7.5 小结

    ASP.NET Core提供了一个非常灵活的配置模型,支持多种不同的基于文件的方式,同时还包括命令行,内存和环境变量等。 它与选项模型无缝工作,让您可以将强类型设置注入到您的应用程序或框架中。 您可以创建自己的自定义configuration providers,它可以与内置的providers一起工作或替换内部的providers,具有极大的灵活性。

results matching ""

    No results matching ""