zoukankan      html  css  js  c++  java
  • ASP.NET Core 1.0 基础之配置

    来源https://docs.asp.net/en/latest/fundamentals/configuration.html

    ASP.NET Core 1.0支持不同的配置选项。应用配置数据可以是来自Json,XML,INI等格式,这些格式都是内建支持。当然配置数据也可以来自环境变量。你也可以写自己的环境provider

    你可以从Github下载样例代码

    获取和设置环境配置##

    ASP.NET Core 1.0的环境系统是经过重新设计的,不像之前的是依赖于System.Configuration和类似web.config之类的xml文件的。新的配置模型中,配置可以从不同的provider中获取,并且这些设置是支持streamlined键值对获取的。使用新的options pattern,应用和框架可以获取配置。

    为了处理配置问题,推荐的做法是在Startup类中,实例化一个Configuration对象,然后使用options pattern来接入不同的配置。

    简单来说,Configuration是一系列配置provider的集合,提供读取和写入键对值的功能。为了Configuration能正常工作,至少要配置一个provider。下例展示了怎样测试作为键对值存储的Configuration。

    // assumes using Microsoft.Framework.ConfigurationModel is specified
    var builder = new ConfigurationBuilder();
    builder.Add(new MemoryConfigurationProvider());
    var config = builder.Build();
    config.Set("somekey", "somevalue");
    
    // do some other work
    
    string setting2 = config["somekey"]; // also returns "somevalue"
    

    Note:你必须设置至少一个provider

    通常情况下,配置数据是分层结构存储的,尤其使用外部文件时,如Json,XML,INI等。在这种情况下,配置数据可以通过分隔符:来获取。考虑如下配置文件

    {
      "Data": {
        "DefaultConnection": {
          "ConnectionString": "Server=(localdb)\mssqllocaldb;Database=aspnet5-WebApplication1-8479b9ce-7b8f-4402-9616-0843bc642f09;Trusted_Connection=True;MultipleActiveResultSets=true"
        }
      },
      "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
          "Default": "Verbose",
          "System": "Information",
          "Microsoft": "Information"
        }
      }
    }
    

    应用使用配置文件来配置连接字符串,获取该值可以使用这样的键Data:DefaultConnection:ConnectionString。
    使用options pattern可以解耦应用所需的配置和获取指定配置的机制。为了使用options pattern,你需要创建自己的设置类(或许是几个不同的类,对应几个不同的内聚的设置组),这样你可以使用options 服务将他们注入你的应用。然后你可以使用configuration或者任何你选择的机制来指定settings。
    Note: 你可以将Configuration实例作为服务存储起来,但是这会不必要地将你的应用和单一配置系统以及特定的配置keys耦合起来。你应该使用Options pattern来避免该问题。

    使用内建的provider##

    配置框架有内置的对JSON,XML和INI配置文件的支持,同样的支持内存中的配置(直接在代码中设置值),以及从环境配置和命令行参数中取得配置。开发者并不局限于一种provider。事实上,若干个provider可以一起使用,这样的话默认的配置会被其他provider提供的配置所覆盖(如果存在的话)。
    通过扩展方法,可以实现对其他配置文件provider的支持。这些方法由ConfigurationBuilder单独调用或者作为fluent API调用,如下

    var config = builder.Build();
    
    builder.AddEntityFramework(options => options.UseSqlServer(config["Data:DefaultConnection:ConnectionString"]));
    config = builder.Build();
    

    configuration providers的顺序是很重要的,因为这决定了如果配置在多个位置的话,哪个配置将会被应用。如上例,如果同样的值存在appsettings.json和环境变量中,环境变量中的配置将会被应用。如果配置存在多个位置,最后一个provider指定的值将会覆盖之前的值。ASP.NET团队推荐将环境变量的配置放在最后,这样本地环境变量将会覆盖任何被部署的配置文件。
    Note: 在shell中通过环境变量覆盖嵌套的值,并不支持“:”,而是使用“__”(double undercore)。

    使用基于环境的配置文件是很有用的,如下

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration providers.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .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=532709
            builder.AddUserSecrets();
        }
    
        builder.AddEnvironmentVariables();
        Configuration = builder.Build();
    }
    

    IHostingEnvironment 服务用来获取当前环境,如果在Development环境,第6行代码将会查找appsettings.Development.json文件,如果存在的话,并使用其中的配置项来重写其他的值,详见Working with Multiple Environments

    Warning:你绝对不应存储密码或其他敏感信息在provider代码中或者配置文件中。你也不应该在开发和测试环境中使用生产环境密码。事实上,这些信息应该在项目树之外指定,这样能避免偶然情况下将其提交到provider仓储中。详见Multiple Environments和管理Safe Storage of Application Secrets

    一种可以利用Configuration优先级顺序的方式是使用默认值,默认值可被覆盖。在如下控制台程序中,username的默认值是在MemoryConfigurationProvider中指定的,如果命令行参数中提供了username的值,那么该值会被重写。你可以查看多个Configuration provider在不同阶段时,程序的输出。

    using System;
    using System.Linq;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Configuration.Memory;
    
    namespace ConfigConsole
    {
        public class Program
        {
            public void Main(string[] args)
            {
                var builder = new ConfigurationBuilder();
                Console.WriteLine("Initial Config Providers: " + builder.Providers.Count());
    
                var defaultSettings = new MemoryConfigurationProvider();
                defaultSettings.Set("username", "Guest");
                builder.Add(defaultSettings);
                Console.WriteLine("Added Memory Provider. Providers: " + builder.Providers.Count());
    
                builder.AddCommandLine(args);
                Console.WriteLine("Added Command Line Provider. Providers: " + builder.Providers.Count());
    
                var config = builder.Build();
                string username = config["username"];
    
                Console.WriteLine($"Hello, {username}!");
            }
        }
    }
    

    但程序运行时,除非命令行参数覆盖,程序将会输出默认值
    default

    使用Options和配置对象##

    使用Options你可以轻易的将任何POCO类转换成设置类。推荐的做法是,在应用中对应某种feature,创建一个良好解耦的配置对象。遵循接口隔离原则(ISP)的同时也满足关注点分离(不同部分的配置是分开管理的,因此减少相互不利影响)。
    如下一个简单的MyOptions的例子

    public class MyOptions
    {
        public string Option1 { get; set; }
        public int Option2 { get; set; }
    }
    

    通过IOptions服务可以将Options注入应用。例如,MVC controller利用IOptions来获取填充index视图所需的配置。

    public class HomeController : Controller
    {
        public HomeController(IOptions<MyOptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }
    
        MyOptions Options { get; }
    
        // GET: /<controller>/
        public IActionResult Index()
        {
            return View(Options);
        }
    }
    

    更多详见依赖注入
    为了启动IOpitons服务,你需要在Startup类中ConfigureServices中调用扩展方法AddOptions()。

    public void ConfigureServices(IServiceCollection services)
    {
        // Setup options with DI
        services.AddOptions();
    }
    

    Index视图显示如下
    index
    通过扩展方法Configure来配置选项。可以通过使用delegate或者绑定options到Configuration。

    public void ConfigureServices(IServiceCollection services)
    {
        // Setup options with DI
        services.AddOptions();
    
        // Configure MyOptions using config
        services.Configure<MyOptions>(Configuration);
    
        // Configure MyOptions using code
        services.Configure<MyOptions>(myOptions =>
        {
            myOptions.Option1 = "value1_from_action";
        });
    
        // Add framework services.
        services.AddMvc();
    

    当绑定options到configuration时,配置类中的属性绑定的key具有property:subproperty:...的形式。例如,MyOptions.Option1所绑定key就是Option1,它是从appsettings.json的option1键中读取的。注意配置键是大小写不敏感的。

    每次调用Configure都添加一个IConfigurations到服务容器中,然后有IOptions来将配置选项提供给应用或框架。如果你想使用别的方式直接配置选项(如从数据库读取设置),你可以直接使用ConfigureOptions<TOptions扩展方法来specify一个你自定义的IConfigureOptions的服务。

    对于同样的配置选项,你可以使用多个IConfiguration服务,他们会按顺序起作用。在上例中Option1和Option2值都在appsettings.json中指定,但是option1的值会被configuration delegate所覆盖。

    写自定义provider##

    除了使用内建的configuration provider,你也可以编写自己的。你只需要继承ConfigurationProvider类,然后populate the Data property with the settings from your configuration provider。

    例子:EF设置###

    你可能希望存储一些应用设置选项到数据库中,使用EF来获取它们。你可以有很多方式存储设置,在本例中,我们创建一个简单的configuration provider,来使用EF读取数据库中的name-value对。
    首先我们定义ConfigurationValue,来存储数据到数据库中。

    public class ConfigurationValue
    {
        public string Id { get; set; }
        public string Value { get; set; }
    }
    

    我们还需要一个ConfigurationContext来使用EF存储或获取配置选项值。

    public class ConfigurationContext : DbContext
    {
        public ConfigurationContext(DbContextOptions options) : base(options)
        {
        }
    
        public DbSet<ConfigurationValue> Values { get; set; }
    
    }
    

    然后创建configuration provider。配置数据通过重写Load方法来载入,它从数据库中读取所有的配置数据。为了演示的目的,如果数据库没有存在和populate,configuration provider会首先创建并初始化数据库。

    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 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;
        }
    }
    

    同时,我们还需要添加AddEntityFramework扩展方法来添加configuration provider

    public static class EntityFrameworkExtensions
    {
        public static IConfigurationBuilder AddEntityFramework(this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> setup)
        {
            return builder.Add(new EntityFrameworkConfigurationProvider(setup));
        }
    }
    

    在下例中,你可以看到如何在应用中使用自定义configuration provider。创建ConfigurationBuilder 来setup你的configuration provders。添加EntityFrameworkConfigurationProvider来指定data provider和连接字符串。怎样配置连接字符串呢?当然是使用配置,添加appsettings.json文件作为configuration provider来启动EntityFrameworkConfigurationProvider。通过复用ConfigurationBuilder,数据中任何配置数据都能够重写appsettings.json中数据。

    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json");
            builder.AddEnvironmentVariables();
            var config = builder.Build();
    
            builder.AddEntityFramework(options => options.UseSqlServer(config["Data:DefaultConnection:ConnectionString"]));
            config = builder.Build();
    
            Console.WriteLine("key1={0}", config["key1"]);
            Console.WriteLine("key2={0}", config["key2"]);
            Console.WriteLine("key3={0}", config["key3"]);
    
        }
    }
    

    运行程序,可以看到如下结果
    config

    总结##

    ASP.NET Core 1.0提供很大灵活性的配置模型,可以支持不同文件类型配置,以及命令行,内存和环境变量等配置。他可以与options无缝连接,所以你可以注入强类型的配置到应用或框架中。同时你也可以创建自己的configuration provider,来和内嵌的provider配合,或者取代它们。

  • 相关阅读:
    mysql常用基本命令
    mysql8.0.13下载与安装图文教程
    k8s ingress 增加跨域配置
    Jenkins 备份恢复插件 thinBackup 使用
    k8s HA master 节点宕机修复
    nginx 跨域问题解决
    mongodb 3.4.24 主从复制
    k8s 线上安装 jenkins并结合 jenkinsfile 实现 helm 自动化部署
    k8s helm 运用与自建helm仓库chartmuseum
    centos6 源码安装 unzip
  • 原文地址:https://www.cnblogs.com/yanbinliu/p/5158486.html
Copyright © 2011-2022 走看看