• Microsoft.Extensions.Options支持什么样的配置类?


    在.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);
    
  • 相关阅读:
    2653 区间xor
    c++位运算
    洛谷P1233 木棍加工
    c++背包问题
    FOC基本调试方法[转]
    用于下载AD官网登录账号:User name: fuxin918@fuxin918.com Passeword: s6c0W1w8
    STC10F10XE定时器中断输出10KHz的方波程序
    学习DSP(三)安装C2833x/C2823x C/C++ 头文件和外设示例-压缩包
    学DSP(二):目标芯片28335,GO!
    学DSP(一):开始
  • 原文地址:https://www.cnblogs.com/Nyarlathotep/p/5812866.html
Copyright © 2020-2023  润新知