uncategorized

讀取客製化Web.config / app.config的element

通常在app.config都是用原本預設的element,不過,今天為了自己的元件的設定,必須透過客製化的element作為元件的config,好久沒有研究這部分,所以,研究一下,終於被我弄出來,因此,在這紀錄一下,讓有後續想用的人可以參考

自訂.config標籤


這裡自訂標籤如下,主要標籤分為三層,第一層Token為最外面標籤,等同於元件要開始讀取此設定的root位置,第二層TokenTarget,定義為設定值得Group集合,在root下,可以設定多個不同的Group,第三層target就是我們要讀得設定參數

1
2
3
4
5
6
<Token>
<TokenTarget>
<target type="File" IgnorePath="" TokenPath="" TokenDuration="10"/>
<target type="DB" IgnorePath="" TokenDuration="10" connectionString=""></target>
</TokenTarget>
</Token>

target每個屬性都代表要給予的參數值,設定好自訂標籤的config,接下來就是要讀取標籤內的資料,Config內只設定這樣還不夠,還必須設定<configSections>中註冊要讀取這客製化標籤的元件名稱,例如

1
<section name="Token" type="CustomeXMLConfig.Token,CustomeXMLConfig" />

在這標籤中的name設定的是自訂標籤的第一層名字也就是Token,在type的設定格式,前者為namespace+第一層的Class名稱,後者為namespace,以這例子,namespace=CustomeXMLConfig,第一層的Class名稱是Token

讀取客製化Config標籤資料


在C#則是把XML的結構進行拆解,每一層其實都是一個物件,所以,先從最裡面的target開始,可以訂定如下的Class,使用之前必須先參考System.Configuration進來

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Target : ConfigurationElement
{
[ConfigurationProperty("type", IsRequired = true)]
public string Type => (string)this["type"];
[ConfigurationProperty("IgnorePath", IsRequired = false)]
public string IgnorePath => (string)this["IgnorePath"];
[ConfigurationProperty("TokenPath", IsRequired = false)]
public string TokenPath => this["TokenPath"] == null ? "" : (string)this["TokenPath"];
[ConfigurationProperty("TokenDuration", IsRequired = false)]
public int TokenDuration => (int)this["TokenDuration"];
[ConfigurationProperty("connectionString", IsRequired = false)]
public string ConnectionString => this["connectionString"] == null ? "" : (string)this["connectionString"];
}

IsRequired是代表這屬性是為必要,如果是必要,在XML設定中就必須放入值進去,在ConfigurationProperty內定義要抓取在target內的屬性標籤名字,所以,這部分可以稱做是Element

再來,就是第二層的TokenTarget,這裡則稱為Collection,在這裡必須告知在Collection裡面要抓的element名稱,必須給定是target

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ConfigurationCollection(typeof(Target))]
public class TokenTarget : ConfigurationElementCollection
{
private const string PropertyName = "target";
public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMapAlternate;
protected override string ElementName => PropertyName;
protected override ConfigurationElement CreateNewElement()
{
return new Target();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Target) element).Type;
}
public Target this[int idx] => (Target)BaseGet(idx);
}

其中,Target this[int idx] => (Target)BaseGet(idx)這一段可以讓你在後續要使用時候,可以列出target所具有的屬性

最後就是第一層的位置,如果在Collection只有一個TokenTarget時候,這邊就可以直接設定要讀取Property為TokenTarget物件,再由TokenTarget物件帶出target物件

1
2
3
4
5
6
7
8
9
public class Token : ConfigurationSection
{
[ConfigurationProperty("TokenTarget")]
public TokenTarget TokenTarget
{
get => ((TokenTarget) (this["TokenTarget"]));
set => this["TokenTarget"] = value;
}
}

以上標籤對應的類別定義好之後,就可以去讀取它了,透過GetSection取得root名稱下的標籤,這邊root名稱為Token

1
var config = System.Configuration.ConfigurationManager.GetSection("Token");

抓出第二層的資訊

1
var token = (config as Token).TokenTarget;

然後,再從第二層物件取得最後一層element的屬性

1
2
3
4
5
for (int i = 0; i < token.Count; i++)
{
Console.WriteLine(token[i].Type);
Console.WriteLine(token[i].TokenDuration.ToString());
}

就這樣就可以把我們想要客製化element中的設定檔讀出來了