谈一谈对网站开发的理解,深圳建设方面上市公司有,定制网站开发都提供那些东西,青岛找网站建设公司哪家好概述我们都知道asp.net core配置信息的读取离不开IConfigurationSource和IConfigurationProvider这两个类#xff0c;ConfigurationSource可以提供一个ConfigurationProvider#xff0c;然后去读取信息。究竟他们之间有着怎样的千丝万缕#xff0c;我们一起来看看源码。首先… 概述我们都知道asp.net core配置信息的读取离不开IConfigurationSource和IConfigurationProvider这两个类ConfigurationSource可以提供一个ConfigurationProvider然后去读取信息。究竟他们之间有着怎样的千丝万缕我们一起来看看源码。首先我们来建立一个.net core控制台项目来运行以下代码class Program{static void Main(string[] args){ConfigurationBuilder configBuilder new ConfigurationBuilder();configBuilder.SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile(appsettings.json);var configFile configBuilder.Build();Console.ReadKey();}}短短几行 代码看起来很简单就是用来读取appsettings.json文件中的配置信息。然而我们今天想搞清楚其背后运行的原理要花点时间。首先、我们根据代码ConfigurationBuilder configBuilder new ConfigurationBuilder();知道创建了一个configBuilder对象其次configBuilder.SetBasePath(Directory.GetCurrentDirectory()) 该代码的调用我们也能大概见名知义获取当前的目录接下来重点来了configBuilder.AddJsonFile(appsettings.json)的实现究竟是怎样的我们来看下源码的实现f12进去后源码如下/// summaryExtension methods for adding see crefT:Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider /./summarypublic static class JsonConfigurationExtensions{/// summaryAdds the JSON configuration provider at paramref namepath / to paramref namebuilder /./summary/// param namebuilderThe see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder / to add to./param/// param namepathPath relative to the base path stored in/// see crefP:Microsoft.Extensions.Configuration.IConfigurationBuilder.Properties / of paramref namebuilder /./param/// returnsThe see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder /./returnspublic static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder,string path){return builder.AddJsonFile((IFileProvider) null, path, false, false);}
}紧接着f12再看实现的源码依然在JsonConfigurationExtensions这个扩展类里面public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder,IFileProvider provider,string path,bool optional,bool reloadOnChange){if (builder null)throw new ArgumentNullException(nameof (builder));if (string.IsNullOrEmpty(path))throw new ArgumentException(SR.Error_InvalidFilePath, nameof (path));return builder.AddJsonFile((ActionJsonConfigurationSource) (s {s.FileProvider provider;s.Path path;s.Optional optional;s.ReloadOnChange reloadOnChange;s.ResolveFileProvider();}));}这时候有没有发现builder.AddJsonFile((ActionJsonConfigurationSource)这个方法里面出现了一个关键的信息点JsonConfigurationSource (JsonConfigurationSource 继承抽象类FileConfigurationSource,而FileConfigurationSourceIConfigurationSource) 。关系如下图 看完上面这个关系图后我们紧接着上面builder.AddJsonFile()的实现源码继续f12往下,源码如下//该代码依然在JsonConfigurationExtensions类里面public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder,ActionJsonConfigurationSource configureSource){return ConfigurationExtensions.AddJsonConfigurationSource(builder, (ActionM0) configureSource);}我们看到上面的扩展方法实现是ConfigurationExtensions.Add...,再往下看实现public static class ConfigurationExtensions{/// summaryAdds a new configuration source./summary/// param namebuilderThe see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder / to add to./param/// param nameconfigureSourceConfigures the source secrets./param/// typeparam nameTSource //// returnsThe see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder /./returnspublic static IConfigurationBuilder AddTSource(this IConfigurationBuilder builder,ActionTSource configureSource)where TSource : IConfigurationSource, new(){TSource source new TSource();if (configureSource ! null)configureSource(source);return builder.Add((IConfigurationSource) source);}
}到这里我们看到了其实就是IConfigurationBuilder调用了Add方法添加了一个数据源JsonConfigurationSource至于JsonConfigurationSource类里面做了什么我们看下实现。public class JsonConfigurationSource : FileConfigurationSource{/// summaryBuilds the see crefT:Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider / for this source./summary/// param namebuilderThe see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder /./param/// returnsA see crefT:Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider //returnspublic override IConfigurationProvider Build(IConfigurationBuilder builder){this.EnsureDefaults(builder);return (IConfigurationProvider) new JsonConfigurationProvider(this);}}JsonConfigurationSource类面的Build方法提供了一个JsonConfigurationProvider类这里再贴下JsonConfigurationProvider类里面的代码/// summaryA JSON file based see crefT:Microsoft.Extensions.Configuration.FileConfigurationProvider /./summarypublic class JsonConfigurationProvider : FileConfigurationProvider{/// summaryInitializes a new instance with the specified source./summary/// param namesourceThe source settings./parampublic JsonConfigurationProvider(JsonConfigurationSource source): base((FileConfigurationSource) source){}/// summaryLoads the JSON data from a stream./summary/// param namestreamThe stream to read./parampublic virtual void Load(Stream stream){try{this.set_Data(JsonConfigurationFileParser.Parse(stream));}catch (JsonException ex){throw new FormatException(SR.Error_JSONParseError, (Exception) ex);}}}关于JsonConfigurationProvider里面的Load就是去读取信息的实现至于Load的具体实现我们不再深究。我们回到最初的控制台configBuilder.Build()看看其的实现public class ConfigurationBuilder : IConfigurationBuilder{/// summaryReturns the sources used to obtain configuration values./summarypublic IListIConfigurationSource Sources { get; } (IListIConfigurationSource) new ListIConfigurationSource();/// summaryGets a key/value collection that can be used to share data between the see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder //// and the registered see crefT:Microsoft.Extensions.Configuration.IConfigurationProvider /s./summarypublic IDictionarystring, object Properties { get; } (IDictionarystring, object) new Dictionarystring, object();/// summaryAdds a new configuration source./summary/// param namesourceThe configuration source to add./param/// returnsThe same see crefT:Microsoft.Extensions.Configuration.IConfigurationBuilder /./returnspublic IConfigurationBuilder Add(IConfigurationSource source){if (source null)throw new ArgumentNullException(nameof (source));this.Sources.Add(source);return (IConfigurationBuilder) this;}/// summaryBuilds an see crefT:Microsoft.Extensions.Configuration.IConfiguration / with keys and values from the set of providers registered in/// see crefP:Microsoft.Extensions.Configuration.ConfigurationBuilder.Sources /./summary/// returnsAn see crefT:Microsoft.Extensions.Configuration.IConfigurationRoot / with keys and values from the registered providers./returnspublic IConfigurationRoot Build(){ListIConfigurationProvider configurationProviderList new ListIConfigurationProvider();foreach (IConfigurationSource source in (IEnumerableIConfigurationSource) this.Sources){IConfigurationProvider configurationProvider source.Build((IConfigurationBuilder) this);configurationProviderList.Add(configurationProvider);}return (IConfigurationRoot) new ConfigurationRoot((IListIConfigurationProvider) configurationProviderList);}}看到这个源码的时候有没有种豁然开朗的感觉前面我们说到IConfigurationBuilder调用了Add方法添加一个数据源并没说添加了一个数据源存在了哪里到底有什么用处现在在上面ConfigurationBuilder类里面看到存在了Sources 集合里面。然后configBuilder.Build()去调用的时候遍历数据源Sources 集合紧接着source (IConfigurationSource)调用了Build方法构建了一个configurationProvider对象存到configurationProviderList集合里面最后在返回一个ConfigurationRoot对象的构造函数里面传递了configurationProviderList集合去执行。贴上ConfigurationRoot的源码public class ConfigurationRoot : IConfigurationRoot, IConfiguration, IDisposable{private readonly IListIConfigurationProvider _providers;private readonly IListIDisposable _changeTokenRegistrations;/// summaryInitializes a Configuration root with a list of providers./summary/// param nameprovidersThe see crefT:Microsoft.Extensions.Configuration.IConfigurationProvider /s for this configuration./parampublic ConfigurationRoot(IListIConfigurationProvider providers){if (providers null)throw new ArgumentNullException(nameof (providers));this._providers providers;this._changeTokenRegistrations (IListIDisposable) new ListIDisposable(providers.Count);foreach (IConfigurationProvider provider in (IEnumerableIConfigurationProvider) providers){IConfigurationProvider p provider;p.Load();this._changeTokenRegistrations.Add(ChangeToken.OnChange((FuncIChangeToken) (() p.GetReloadToken()), (Action) (() this.RaiseChanged())));}}
}public class ConfigurationRoot : IConfigurationRoot, IConfiguration, IDisposable{private readonly IListIConfigurationProvider _providers;private readonly IListIDisposable _changeTokenRegistrations;/// summaryInitializes a Configuration root with a list of providers./summary/// param nameprovidersThe see crefT:Microsoft.Extensions.Configuration.IConfigurationProvider /s for this configuration./parampublic ConfigurationRoot(IListIConfigurationProvider providers){if (providers null)throw new ArgumentNullException(nameof (providers));this._providers providers;this._changeTokenRegistrations (IListIDisposable) new ListIDisposable(providers.Count);foreach (IConfigurationProvider provider in (IEnumerableIConfigurationProvider) providers){IConfigurationProvider p provider;p.Load();this._changeTokenRegistrations.Add(ChangeToken.OnChange((FuncIChangeToken) (() p.GetReloadToken()), (Action) (() this.RaiseChanged())));}}
}看到没最后providers去调用了load方法。结语就上面的控制台代码来说IConfigurationSource对应的实现是JsonConfigurationSourceIConfigurationProvider抽象类ConfigurationProvider对应的实现为JsonConfigurationProvider。如果我们要换成别的文件格式呢比如ini,怎样自定义配置源呢大家可以先想想其实也很简单下次跟大家分享。最后说真的.netCore源码真的特别优秀很值得花一番时间去看看从其中可以学到许多架构知识— —往日推荐— —github上star23k的程序员必备通用简历模板Windows.NetCoregitIIS在Jenkins上的自动化部署入门C# 创建单例你会几种方式一个小时开发的直播推拉流软件来了关于数据库建表是否建立外键的争论你有什么样的观点常见的23种设计模式彩图过来了解一下什么是线程同步又如何解决线程同步问题使用.net 和Selenium模拟百度登录四种软件架构看看你属于哪个层次.net爬虫是一门必修课.net下使用Selenium、PhantomJS在.net平台使用QuartzTopshelf创建windows服务极简实用的Asp.NetCore模块化框架决定免费开源了关于Asp.Net Core如何更完美地配置swaggerASP.NET Core如何自动生成小写的破折号路由