Asp.Net Core- 配置組件詳解

咱們以前寫的配置都是放置在配置文件Web.config或者app.config中,.net core提供了全新的配置方式,能夠直接寫在內存中或者寫在文件中。html

.Net Core的配置API主要體如今3個類中Configuration、ConfigurationBuilder、ConfigurationProvider中。json

配置文件其實就是一個鍵值對。Configuration以樹形結構描述了這些鍵值對之間的關係。咱們的配置文件好比project.json是怎麼轉換成Configuration樹形結構的呢?app

Microsoft.Extensions.Options這個命名空間下的類提供了文件向Configuration的轉換。ide

1、配置文件分爲3種結構ui

1. 邏輯結構:就是咱們看到的結構,樹形結構。this

2. 原始結構:就是文件自己的結構,好比xml、json等等。spa

3. 物理結構:介於二者之間的結構,鍵值對。.net

配置組件的最終目的就是把原始結構轉化成邏輯結構,在具體轉換過程當中,先找到對應的ConfigurationProvider轉化爲物理結構數據字典,而後再由ConfigurationBuilder轉化爲邏輯結構Configuration對象。code

2、Configurationxml

Configuration對象泛指繼承自接口IConfiguration的對象。這個接口以下:

namespace Microsoft.Extensions.Configuration

{

using Microsoft.Extensions.Primitives;

using System;

using System.Collections.Generic;

using System.Reflection;

public interface IConfiguration

{

IEnumerable<IConfigurationSection> GetChildren();

IChangeToken GetReloadToken();

IConfigurationSection GetSection(string key);

string this[string key] { get; set; }

}

}
View Code

 

這個接口GetChildren表示全部的ConfigurationSection對象;GetSection根據key值獲得ConfigurationSection對象。

繼承自這個接口的對象分別是ConfigurationRoot和ConfigurationSection,分別表示配置的根節點和葉子節點。

ConfigurationRoot還繼承自接口IConfigurationRoot接口,代碼以下:

namespace Microsoft.Extensions.Configuration

{

using System;

public interface IConfigurationRoot : IConfiguration

{

void Reload();

}

}
View Code

 

這個接口只有一個方法Reload從新加載,當調用這個方法的時候,在這棵樹下的全部的節點都會從新加載。

ConfigurationSection還繼承自IConfigurationSection,代碼以下:

namespace Microsoft.Extensions.Configuration

{

using System;

public interface IConfigurationSection : IConfiguration

{

string Key { get; }

string Path { get; }

string Value { get; set; }

}

}
View Code

 

Key表示父節點的名稱;Path表示當前節點的路徑,用「:」隔開;Value只有在葉子節點纔有值,非葉子節點返回Null。

3、ConfigurationProvider

ConfigurationProvider對象泛指實現了接口IConfigurationProvider的對象。

namespace Microsoft.Extensions.Configuration

{

using Microsoft.Extensions.Primitives;

using System;

using System.Collections.Generic;

using System.Runtime.InteropServices;

public interface IConfigurationProvider

{

IEnumerable<string> GetChildKeys(IEnumerable<string> earlierKeys, string parentPath);

IChangeToken GetReloadToken();

void Load();

void Set(string key, string value);

bool TryGet(string key, out string value);

}

}
View Code

 

而繼承自這個接口的是一個抽象類ConfigurationProvider,代碼以下:

public abstract class ConfigurationProvider : IConfigurationProvider

{

// Fields

private ConfigurationReloadToken _reloadToken;

// Methods

protected ConfigurationProvider();

public virtual IEnumerable<string> GetChildKeys(IEnumerable<string> earlierKeys, string parentPath);

public IChangeToken GetReloadToken();

public virtual void Load();

protected void OnReload();

private static string Segment(string key, int prefixLength);

public virtual void Set(string key, string value);

public virtual bool TryGet(string key, out string value);

// Properties

protected IDictionary<string, string> Data { get; set; }

}
View Code

 

由於這個類的最終目的就是轉化爲數據字典,因此,這個類的方法大部分都是針對數據字典,方法的參數中都有key值。

不一樣的數據源都是繼承自這個抽象類,重寫本身的方法。

Load方法從數據源加載數據,針對不一樣的數據源子類能夠重寫;TryGet根據key值獲取數據值;Set方法設置數據值,由於這個類的主要功能是從數據源讀取數據轉化爲數據字典,因此Set的值只保存在內存中。

4、ConfigurationBuilder

泛指實現了接口IConfigurationBuilder的對象。他的做用就是根據ConfigurationProvider提供的數據字典,把數據字典轉化爲ConfigurationRoot對象。接口以下:

namespace Microsoft.Extensions.Configuration

{

using System.Collections.Generic;

public interface IConfigurationBuilder

{

IConfigurationBuilder Add(IConfigurationSource source);

IConfigurationRoot Build();

Dictionary<string, object> Properties { get; }

IEnumerable<IConfigurationSource> Sources { get; }

}

}
View Code

 

主要經過Build方法實現把數據字典轉化爲ConfigurationRoot。

不管是ConfigurationRoot仍是ConfigurationSection自己都沒有封裝任何形式的對配置的讀取操做,全部的讀取操做都是在ConfigurationProvider對象中。

在ConfigurationRoot和ConfigurationSection組成的樹形結構中,並無在代碼中直接保存這種結構,而是每一個ConfigurationSection中都有一個ConfigurationRoot對象,直接是對根節點的引用。而只有根節點中有對ConfigurationProvider的調用。也就是在每一個葉子節點中都有一個對於根節點的引用。這樣當咱們想要獲取某個節點的具體值時,先找到根節點,再經過根節點找到ConfigurationProvider,經過ConfigurationProvider對象獲取配置值。

還有一個對象ConfigurationPath,主要封裝對樹層級結構的計算,代碼以下:

namespace Microsoft.Extensions.Configuration

{

using System;

using System.Collections.Generic;

public static class ConfigurationPath

{

public static readonly string KeyDelimiter = ":";

public static string Combine(IEnumerable<string> pathSegments)

{

if (pathSegments == null)

{

throw new ArgumentNullException("pathSegments");

}

return string.Join(KeyDelimiter, pathSegments);

}

public static string Combine(params string[] pathSegments)

{

if (pathSegments == null)

{

throw new ArgumentNullException("pathSegments");

}

return string.Join(KeyDelimiter, pathSegments);

}

public static string GetParentPath(string path)

{

if (!string.IsNullOrEmpty(path))

{

int length = path.LastIndexOf(KeyDelimiter, (StringComparison) StringComparison.OrdinalIgnoreCase);

if (length != -1)

{

return path.Substring(0, length);

}

}

return null;

}

public static string GetSectionKey(string path)

{

if (!string.IsNullOrEmpty(path))

{

int num = path.LastIndexOf(KeyDelimiter, (StringComparison) StringComparison.OrdinalIgnoreCase);

if (num != -1)

{

return path.Substring(num + 1);

}

}

return path;

}

}

}
View Code

 

Combine方法實現把路徑鏈接成一個完整的路徑。

以上對象之間的關係圖以下:

http://images2015.cnblogs.com/blog/19327/201604/19327-20160419220618335-900092396.png

綜上,配置模塊的最終目的是要把原始的配置文件好比:json、xml轉換爲一個ConfigurationRoot對象,這個對象是一個樹形結構,下邊是ConfigurationSection對象。當咱們要獲取某個配置時,經過ConfigurationRoot的ConfigurationProvider獲取,每一個ConfigurationSection都有一個對於根節點的引用。

 

後記:當須要讀取一個配置文件的時候,調用ConfigurationBuilder的build方法把文件內容轉換爲ConfigurationRoot對象,在這個方法執行過程當中,會調用根據配置文件的不一樣調用相關的ConfigurationProvider ,而後調用ConfigurationProvider的Load方法,把配置文件轉換成數據字典;而後再回到ConfigurationBuilder中把數據字典轉化爲ConfigurationRoot。

 

參考連接:http://www.cnblogs.com/artech/p/asp-net-core-config-01.html

相關文章
相關標籤/搜索