在.Net core中,微软放弃了笨重基于XML的.Config配置文件(好吧,像我这种咸鱼早都忘了如何自己写一个Section了)。

现在主推新的高度可扩展的配置文件(参见此处

对于新的配置系统,既可以通过IConfigurationSection.Value手工一个个获取配置项的值(神烦无比,别问我怎么知道的),也可以通过选择模式(options pattern)通过POCO(Plain Old CLR Object)类读取配置(参见如下代码片段:)

//配置POJO如下:
/*
public class FooConfig
{
public string Name { get; set; }
}
*/
//加载配置
var configBuilder = new ConfigurationBuilder();
configBuilder.SetBasePath(GetConfigDir());
configBuilder.AddJsonFile("config.json");
var configuration = configBuilder.Build(); //初始化默认DI容器
var services = new ServiceCollection();
services.AddOptions();
services.Configure<FooConfig>(configuration);//从配置文件读取FooConfig
var serviceProvider = services.BuildServiceProvider(); //获取FooConfig实例
var fooConfigOptions = serviceProvider.GetService<IOptions<FooConfig>>();
var fooConfig = fooConfigOptions.Value;
var name=fooConfig.Name;

看上去一切都好,直到当FooConfig中增加了一个IEnumerable<string>类型的属性,用来读取列表时:

public class FooConfig
{
public string Name { get; set; }
public IEnumerable<string> ValueList { get; set; }
}

跳出一个明晃晃的InvalidOperationException。说是不支持接口类型。

那么问题来了,Microsoft.Extensions.Options究竟支持什么样的配置类?

由于现今.Net core的文档少的可怜,这个问题就只有自己翻代码求解了。

首先看这段代码:

services.Configure<FooConfig>(configuration);//从配置文件读取FooConfig

似乎,一切秘密就在这个Configure扩展方法中?

首先查看Configure扩展方法的源码,我们又被带到了ConfigureFromConfigurationOptions类上。那么,这个类是如何读取配置的呢?

细节请自行查看,总结下,就是调用了Microsoft.Extensions.Configuration.ConfigurationBinder.Bind方法以绑定配置到配置类实例上(此处应有源码)。

细读代码,总结如下:

  1. 如果配置类中某个属性无对应配置,则不予处理(此时违反以下任何规则都没事,反正不处理)

  2. 配置类中所有属性的类型必须为IConfigurationSection或实际类型,不能为其他接口类型(interface)或抽象类(abstract clas)

  3. 如果配置类中某个属性无公共Get方法,忽略之

  4. 如果配置类中某个属性无公共Set方法,且属性无值(Get方法不返回值),则忽略之(这条太细致了吧……因为属性值本身还可能可以绑定配置)

  5. 对于配置的叶子节点(就是IConfigurationSection.Value有值的那些节点),则通过TypeDescriptor.GetConverter(type).ConvertFromInvariantString(value)转换字段(Nullable字段特殊处理,故而只要其基础类型支持转换就行)

  6. 对于非配置叶子节点的属性,支持以下集合类型:一维数组(最普通的array)、实现了ICollection<T>的集合、实现了IDictionary<TKey,TValue>的集合(TKey必须为string)、能够创建实例的类(都说了接口和抽象类不支持了嘛)

其实,如果不想使用IOptions,还可以直接Bind嘛:

var fooConfig=new FooConfig();
ConfigurationBinder.Bind(configuration,fooConfig);

Microsoft.Extensions.Options支持什么样的配置类?的更多相关文章

  1. 乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 官方扩展集锦(Microsoft.Extensions on Nuget)

    什么是Microsoft.Extensions .NET Platform Extensions是一套.Net官方的API集合,提供了一些常用的编程模式和实用工具,例如依赖项注入.日志记录.缓存.Ho ...

  2. 使用 Microsoft.Extensions.DependencyInjection 进行依赖注入

    没有 Autofac DryIoc Grace LightInject Lamar Stashbox Unity Ninject 的日子,才是好日子~~~~~~~~~~ Using .NET Core ...

  3. DotNetCore跨平台~一起聊聊Microsoft.Extensions.DependencyInjection

    写这篇文章的心情:激动 Microsoft.Extensions.DependencyInjection在github上同样是开源的,它在dotnetcore里被广泛的使用,比起之前的autofac, ...

  4. Asp.Net Core 2.0 项目实战(9) 日志记录,基于Nlog或Microsoft.Extensions.Logging的实现及调用实例

    本文目录 1. Net下日志记录 2. NLog的使用     2.1 添加nuget引用NLog.Web.AspNetCore     2.2 配置文件设置     2.3 依赖配置及调用     ...

  5. .NET Core采用的全新配置系统[5]: 聊聊默认支持的各种配置源[内存变量,环境变量和命令行参数]

    较之传统通过App.config和Web.config这两个XML文件承载的配置系统,.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命令行参 ...

  6. .NET Core采用的全新配置系统[3]: “Options模式”下的配置是如何绑定为Options对象

    配置的原子结构就是单纯的键值对,并且键和值都是字符串,但是在真正的项目开发中我们一般不会单纯地以键值对的形式来使用配置.值得推荐的做法就是采用<.NET Core采用的全新配置系统[1]: 读取 ...

  7. “Options模式”下的配置是如何绑定为Options对象

    “Options模式”下的配置是如何绑定为Options对象 配置的原子结构就是单纯的键值对,并且键和值都是字符串,但是在真正的项目开发中我们一般不会单纯地以键值对的形式来使用配置.值得推荐的做法就是 ...

  8. asp.net core 2.0 Microsoft.Extensions.Logging 文本文件日志扩展

    asp.net core微软官方为日志提供了原生支持,有如下实现 Console Debug EventLog AzureAppServices TraceSource EventSource 并且在 ...

  9. Microsoft.Extensions.DependencyInjection不同版本导致EF出现内存泄露。

    我的代码里将IServiceProvider放入ServiceLocator中遇到的问题. 注:以下所有例子都是Console里的结论,AspNetCore里不管怎么玩都没有问题,有其他帖子测试出在A ...

随机推荐

  1. SBT 构建scala eclipse开发

    scala eclipse sbt 应用程序开发 搭建Eclipse开发Scala应用程序的一般步骤 一.环境准备: 1.Scala : http://www.scala-lang.org/ 2.Sc ...

  2. JDK 环境变量设置

    .net转JAVA了.记心不好,记录一下. 安装好jdk(64位)后找到我的电脑(右键)>属性>高级选项卡>环境变量>,里面有管理员的用户变量,有系统变量.我选的是系统变量.点 ...

  3. RMQ(范围最值问题)算法学习

    RMQ算法适合求解对一个数组多次查询给定范围内的最值. 预处理操作: 令d[i,j]表示从i开始,长度为2^j的一段元素的最值,可以用递推公式写出d[i,j] = min{ d[i][j-1], d[ ...

  4. 使用css3中calc()进行自适应布局

    calc()能做什么? calc()可以通过计算得到元素的宽度或者高度,让我们很容易进行自适应布局. 你可以为一个div元素,使用百分比.em.px和rem单位值计算出其宽度或者高度,比如说“widt ...

  5. CentOS使用virtualenv搭建独立的Python环境-python虚拟环境

    CentOS使用virtualenv搭建独立的Python环境-python虚拟环境 virtualenv可以搭建虚拟且独立的python环境,可以使每个项目环境与其他项目独立开来,保持环境的干净,解 ...

  6. 快考试了,尽快写完HashTable。

    (1)Count Primes 质数(素数):在大于1 的自然数中,除了1和它本身之外,不能被任何其他整数整除. 解题思路:使用一个boolean类型的数组,从i(2) 开始循环,将小于N的i的倍数都 ...

  7. Android菜鸟成长记6 -- 网络连接的检查

    在android开发中我们要经常考虑到各种问题.在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒.一般可以通过ConnectivityManager ...

  8. Android四大组件之——Activity的生命周期(图文详解)

        转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com       [Andro ...

  9. Echarts data数据为空时,显示“-”

    { name:'2007', type:'bar', data:["","",""]} 解决办法: 写成data:["" ...

  10. C# 关于时间

    1.2016/7/8 00:10:10 转换成 2016-07-08T 00:10:10 在用VB动态调用WevService的时候,传入的时间格式为2016/7/8 00:10:10,导致调用出错, ...