配置就是一個裝配數據字典的過程,一個字典也就是一個鍵值對,所以從配置就是鍵值對。
在asp.net core中關於配置是由四個基本的類型來支撐的,是①IConfigurationSource②IConfigurationProvider③IConfigurationBuilder④IConfiguration。
最終我們在程序中使用的是IConfiguration這個類型來獲取配置中存入的信息,其他三個類型都是在asp.net core的啟動過程中來幫助完成這個IConfiguration類型的。IConfigurationRoot這個接口繼承IConfiguration接口,可以看作是一個東西(我現在的只是水平)。
具體過程是這樣的:
IConfigurationBuilder這個類有一個Builder方法,在ICOnfigurationBuilder這個默認實現類ConfigurationBuilder:
public class ConfigurationBuilder : IConfigurationBuilder { /// <summary> /// Returns the sources used to obtain configuration values. /// </summary> public IList<IConfigurationSource> Sources { get; } = (IList<IConfigurationSource>) new List<IConfigurationSource>(); /// <summary> /// Gets a key/value collection that can be used to share data between the <see cref="T:Microsoft.Extensions.Configuration.IConfigurationBuilder" /> /// and the registered <see cref="T:Microsoft.Extensions.Configuration.IConfigurationProvider" />s. /// </summary> public IDictionary<string, object> Properties { get; } = (IDictionary<string, object>) new Dictionary<string, object>(); /// <summary>Adds a new configuration source.</summary> /// <param name="source">The configuration source to add.</param> /// <returns>The same <see cref="T:Microsoft.Extensions.Configuration.IConfigurationBuilder" />.</returns> public IConfigurationBuilder Add(IConfigurationSource source) { if (source == null) throw new ArgumentNullException(nameof (source)); this.Sources.Add(source); return (IConfigurationBuilder) this; } /// <summary> /// Builds an <see cref="T:Microsoft.Extensions.Configuration.IConfiguration" /> with keys and values from the set of providers registered in /// <see cref="P:Microsoft.Extensions.Configuration.ConfigurationBuilder.Sources" />. /// </summary> /// <returns>An <see cref="T:Microsoft.Extensions.Configuration.IConfigurationRoot" /> with keys and values from the registered providers.</returns> public IConfigurationRoot Build() { List<IConfigurationProvider> configurationProviderList = new List<IConfigurationProvider>(); foreach (IConfigurationSource source in (IEnumerable<IConfigurationSource>) this.Sources) { IConfigurationProvider configurationProvider = source.Build((IConfigurationBuilder) this); configurationProviderList.Add(configurationProvider); } return (IConfigurationRoot) new ConfigurationRoot((IList<IConfigurationProvider>) configurationProviderList); } }
有兩個關鍵的地方比較重要:
一個是:
public IList<IConfigurationSource> Sources { get; } = (IList<IConfigurationSource>) new List<IConfigurationSource>();
這個list維護一個IConfigurationSource的集合,IConfigurationSource有一個Build方法來生成IConfigurationProvider,后面再說。
另一個是:
public IConfigurationRoot Build() { List<IConfigurationProvider> configurationProviderList = new List<IConfigurationProvider>(); foreach (IConfigurationSource source in (IEnumerable<IConfigurationSource>) this.Sources) { IConfigurationProvider configurationProvider = source.Build((IConfigurationBuilder) this); configurationProviderList.Add(configurationProvider); } return (IConfigurationRoot) new ConfigurationRoot((IList<IConfigurationProvider>) configurationProviderList); }
Build方法最終就是產生一個IConfigurationRoot類型。看一下里面的構造:
首先定義一個List裝IConfigurationProvider的集合,然后遍歷source集合,在遍歷的邏輯內部將每一個IConfigurationSource轉換為ConfigurationProvider之后裝入這個IConfigurationProvider的list中,最后,再用這個list去初始化一個IConfigurationRoot。到此,我們就可以用DI來獲取這個類型來找到我們想要的配置項了。
需要注意的是不同的配置源都有相應的類型的IConfigurationSource和IConfigurationProvider,比如:JsonConfigurationProvider和JsonConfigurationSource,這兩個是用來配置json數據配置文件的,還有關於命令行的,環境變量的,等等,都是類似的,在學習源碼的時候,多看一下就是了。