原文:https://docs.asp.net/en/latest/fundamentals/configuration.html

ASP.NET 5支持多种配置选项。 应用的配置文件可以是JSON,XML,INI格式,也可以是来自系统环境变量。而且你还可以写自己的自定义configuration provider

下载本文示例代码

获取设置configuration

ASP.NET 5的重构了之前依赖于System.Configuration和xml格式的配置文件(如web.config)。

如果你在ASP.NET应用中使用setting的话,建议你只在你应用的Startup类中实例化Configuration。然后使用Option pattern进入独立的settings。

最简单的说,Configuration就是一个source的集合,提供了读写键值对的功能。你最起码得给Configuration配置一个source。下面的代码展示如何使用Configuration做为一个键值对存储:

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

注意:

你至少要设置一个source。

通常我们的configuration键存在一个层级关系。ASP.NET5通过使用:号分隔来实现。例如,有如下的appsettings.json文件:

{
"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来获取ConnectionString的值。

使用options pattern可以创建你自己的配置类,通过使用options service注入到你的应用中。

注意:

你可以将你的Configuration实例做为一个服务存储起来,但是这样以来你的系统依赖一个单一的configuration,而且所有的配置都在这个单一的configuration里面。可以使用过Options pattern 来避免这个问题。

使用built-in providers

configuration framework的built-it支持JSON, XML, 和INI配置文件,同样还支持内存configuraiton,环境变量configuratin和命令行参数的configuration。可以同时使用多种configuration source。

使用ConfigurationBuilder类来添加configuration source。支持链式写法。

var builder = new ConfigurationBuilder(".");
builder.AddJsonFile("appsettings.json");
builder.AddEnvironmentVariables();
var config = builder.Build();

上面configuration source的顺序非常重要,他决定了优先级。越后添加的configuration source优先级越高。在上面的例子中,如果appsetting.json和环境变量都设置了同一个键,环境变量这个source的优先级会高,会使用环境变量中对应的键值覆盖appsettings.json中的键值。

注意:

环境变量不支持:,我们使用__(两个下划线)来代替。

针对不同的环境(debug,release,test)使用不同的配置文件非常有用。可以通过下面的例子来实现。

public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
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();
}

IHostingEnviroment被用来获取当前的环境。在Development环境中,上面的高亮的代码会是appsettings.Development.json,会使用这个文件的值来覆盖其他的文件的值。更多请见Working with Multiple Environments

警告:

你不应该在源代码或者配置文件中存储如密码一样的敏感数据。这样的敏感数据不应该在项目里面,这样你也不会意外的把他们提交到源代码仓储中去了。更多请见:Working with Multiple Environments and managing Safe Storage of Application Secrets

下面的例子中在MemoryConfigurationSource中设置了username,但是被命令行参数的username覆盖了:

using System;
using System.Linq;
using Microsoft.Framework.Configuration; namespace ConfigConsole
{
public class Program
{
public void Main(string[] args)
{
var builder = new ConfigurationBuilder();
Console.WriteLine("Initial Config Sources: " + builder.Sources.Count()); var defaultSettings = new MemoryConfigurationSource();
defaultSettings.Set("username", "Guest");
builder.Add(defaultSettings);
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.Get("username"); Console.WriteLine($"Hello, {username}!");
}
}
}

运行结果如下:

使用Options和configuration对象

使用Options 可以很方便的把任何类转换成一个配置类。 推荐你为不同的应用模块创建对应的配置对象,不要是整个应用只有一个配置对象。

下面是一个简单的MyOptions类:

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

Options可以通过使用IOptions<TOptions>注入到你的应用。如下:

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

关于依赖注入的信息见,Dependency Injection

为了使用IOptions<TOption>,你需要在在startup类中有如下设置:

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

index视图显示option的值:

使用Configure<TOption>来配置你的Options。可以使用委托来配置你的options或者绑定你的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";
}); services.AddMvc();
}

当你绑定options到configuration,你options的每一个属性绑定成了configuration的键(property:subproperty:....)。例如,MyOptions.Option1属性绑定到了Options1这个键,读取appsettings.json文件的options1。注意了configuration的键是大小写不敏感的。

每次调用Configuration<TOptions>都会添加一个IConfigureOptions<TOption>服务到服务容器。

对同一个option类可以有多个IConfigureOptions<TOption>,他们的优先级同样依赖于add的顺序。上面的例子中appsettings.json有Option1和Option2,但是Option1的值被下面使用委托的覆盖了。

写自定义providers

除了使用the built-in configuration source providers,我们可以自己写一个自定义的provider。需要继承自ConfigurationSource。

例子: Entity Framework Settings

你可能希望将你的配置存储在数据库里面,通过使用Entity Framework来获取他们。下面的例子,我们创建一个简单的configuration source使用EF来读取来自数据库的键值对。

首先定义ConfigurationValue实体。用来在数据库中存储配置:

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

现在需要一个ConfigurationContext来做为DbContext:

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

接下来,创建见一个继承自ConfigurationSource的configuration source。覆盖Load方法来加载配置:

public class EntityFrameworkConfigurationSource : ConfigurationSource
{
public EntityFrameworkConfigurationSource(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;
}
}

接下来,我们创建一个EntityFrameworkExtensions在里面添加IConfigurationBuilder的一个扩展方法,用于添加configuration source:

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

使用自定义provider:

public class Program
{
public 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.Get("key1"));
Console.WriteLine("key2={0}", config.Get("key2"));
Console.WriteLine("key3={0}", config.Get("key3")); }
}

结果如下:

[译]ASP.NET 5 Configuration的更多相关文章

  1. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  2. [译]Asp.net MVC 之 Contorllers(二)

    URL路由模块 取代URL重写 路由请求 URL路由模块的内部结构 应用程序路由 URL模式和路由 定义应用程序路由 处理路由 路由处理程序 处理物理文件请求 防止路由定义的URL 属性路由 书接上回 ...

  3. [译]ASP.NET Core 2.0 系列文章目录

    基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...

  4. [译]ASP.NET 5: New configuration files and containers

    原文:http://gunnarpeipman.com/2014/11/asp-net-5-new-configuration-files-and-containers/ ASP.NET vNext提 ...

  5. [译]Asp.net MVC 之 Contorllers(一)

    Asp.net MVC contorllers 在Ajax全面开花的时代,ASP.NET Web Forms 开始慢慢变得落后.有人说,Ajax已经给了Asp.net致命一击.Ajax使越来越多的控制 ...

  6. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(八)

    使用 HttpResponse 对象 HttpResponse 对象是与 HttpRequest 对象相对应的,用来表示构建中的响应.它当中提供了方法和属性可供我们自定义响应,有一些在使用 MVC 视 ...

  7. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(七)

    使用 HttpRequest 对象 HttpRequest 对象描述的是一个正在被处理的 HTTP 请求.下表列举了 HttpRequest 中的属性,它们提供了当前请求的相关信息(HttpReque ...

  8. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(六)

    使用 HttpApplication 对象 ASP.NET 框架中的许多类都提供了许多很方便的属性可以直接映射到 HttpContext 类中定义的属性.这种交叠有一个很好的例子就是 HttpAppl ...

  9. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(五)

    ASP.NET 上下文对象 ASP.NET 提供了一系列对象用来给当前请求,将要返回到客户端的响应,以及 Web 应用本身提供上下文信息.间接的,这些上下文对象也可以用来回去核心 ASP.NET 框架 ...

随机推荐

  1. [转]ASP.NET Core 之 Identity 入门(三)

    本文转自:http://www.cnblogs.com/savorboard/p/aspnetcore-identity3.html 前言 在上一篇文章中,我们学习了 CookieAuthentica ...

  2. AngularJS笔记---注册服务

    在前面的笔记中,了解到AngularJS的后台控制可以在Controller里面实现. 可是如果所有的逻辑代码都写到Controller会显得该Controller过于臃肿. 不方便维护, Angul ...

  3. MMORPG大型游戏设计与开发(服务器 游戏场景 搜索机)

    双十一注定是忙碌的日子,所以到了现在我才将今天自己学习的内容拿出来跟大家分享.搜索机是我自己暂时取的名字,其实简单的说就是场景里提供搜索的一个工具,负责场景对象的范围搜索和获取.空洞的理论总是让人一头 ...

  4. 程序员的修养 -- 如何写日志(logging)

      在程序中写日志是一件非常重要,但是很容易被开发人员忽视的地方.写好程序的日志可以帮助我们大大减轻后期维护压力. 在实际的工作中,开发人员往往迫于的巨大时间压力,而写日志又是一个非常繁琐的事情,往往 ...

  5. 三维网格补洞算法(Radial Basis Function)

    在逆向工程中,由于设备或模型的原因,我们获取得到的三维模型数据往往并不完整,从而使得生成的网格模型存在孔洞,这对后续的模型分析会造成影响.下面介绍一种基于径向基函数(RBF:Radial Basis ...

  6. 参数命令化 防止Sql注入

    1.先在数据库中完成储存过程 create proc usp_selectStudent ) as select * froom student where StudentName=@studentN ...

  7. Oracle体系中各个组件的含义

    首先看张图 下面来解释下这个图. 对于一个数据库系统来说,假设这个系统没有运行,我们所能看到的和这个数据库相关的无非就是几个基于操作系统的物理文件,这是从静态的角度来看,如果从动态的角度来看呢,也就是 ...

  8. 以libfuse为例介绍rpm打包工具rpmbuild的使用和SPEC文件的编写

    一.rpmbuild命令的安装 yum install rpm-build 二.用法 rpmbuild -bb XXXX.spec或者rpmbuild -ba XXX.tar.gz 三.目录概述 rp ...

  9. 栈的理解以及如何计算程序所需栈的大小并在IAR中设置栈

    文章首发于浩瀚先森博客 #栈的理解 一个程序大体上讲都是由变量和函数组合而成,变量有全局变量和局部变量,还有函数间传值的参数以及返回值. Stack是为了程序运行过程中临时保存所需数据而在内存里分配的 ...

  10. SQLite剖析之动态内存分配

    SQLite通过动态内存分配来获取各种对象(例如数据库连接和SQL预处理语句)所需内存.建立数据库文件的内存Cache.保存查询结果. 1.特性    SQLite内核和它的内存分配子系统提供以下特性 ...