雖然App.config是很老的東西了,但有時候還是蠻好用的.自訂區段可以讓你的App.config有更好的結構.一些Open Source的外掛模組也是用這一種方式去做設定的.
先定好目標是在app.config的<configuration>區定義一個自訂的<section>,然後section的內容是一個列表,就好像connection string的列表一樣,每一個entry就是一個<add>.結果如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="MyCustomSection" type="MyNameSpace.Config.MySection, MyCompileOutput" />
</configSections>
<connectionStrings>
</connectionStrings>
<appSettings>
</appSettings>
<MyCustomSection>
<MyValues>
<add StationId="O03" MaxPga="5.23" MaxIntensity="1"/>
<add StationId="O05" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O07" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O11" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O14" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O44" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O47" MaxPga="6.11" MaxIntensity="4"/>
<add StationId="O60" MaxPga="6.11" MaxIntensity="4"/>
</MyValues>
</MyCustomSection>
</configuration>有一個重要的地方是,type設定好類別名稱後,後面要接一個組件名稱,不然會找不到類別.
要達到這個目的,要用到幾個類別: ConfigurationSection, ConfigurationElementCollection, ConfigurationElement.顧名思義就是ConfigurationSection對應Section,ConfigurationElementCollection對應MyValues,ConfigurationElement對應一個<add>.
寫一個Section Class繼承ConfigurationSection,我們的Section裡只有一個列表,所以就有一個回傳列表的方法,要注意的是ConfigurationProperty第一個參數字串就是你app.config裡對應的tag名稱.當你需要修改Section裡的資料時才需要override IsReadOnly()這個方法.
public class MySection : ConfigurationSection
{
public override bool IsReadOnly()
{
//return base.IsReadOnly();
return false;
}
[ConfigurationProperty("MyValues", IsRequired = false, IsDefaultCollection = true)]
public MaxValueCollection MaxValues
{
get
{
MaxValueCollection maxValues = (MaxValueCollection)base["MyValues"];
return maxValues;
}
}
}回傳的MaxValueCollection就是繼承ConfigurationElementCollection的類別,沒甚麼特別就不說明了.
public class MaxValueCollection : ConfigurationElementCollection
{
public MaxValueCollection() { }
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.AddRemoveClearMap;
}
}
public MaxValueElement this[int index]
{
get { return (MaxValueElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
}
public MaxValueElement this[string key]
{
get { return (MaxValueElement)BaseGet(key); }
set
{
if (BaseGet(key) != null)
{
BaseRemove(key);
BaseAdd(value);
}
}
}
protected override ConfigurationElement CreateNewElement()
{
return new MaxValueElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MaxValueElement)element).StationId;
}
public void Add(MaxValueElement element)
{
BaseAdd(element);
}
//public void Clear()
//{
// BaseClear();
//}
//public void Remove(string name)
//{
// BaseRemove(name);
//}
}MaxValueElement繼承ConfigurationElementCollection,就是實際上記錄著資料的Entry.要注意ConfigurationProperty裡的字串就是<add>裡面Attribute的名稱,用base[]取得值時也要用相同的字串.
public class MaxValueElement : ConfigurationElement
{
public MaxValueElement()
{
}
public MaxValueElement(string stationId, float maxPga, int maxIntensity)
{
base["StationId"] = stationId;
base["MaxPga"] = maxPga;
base["MaxIntensity"] = maxIntensity;
}
public override bool IsReadOnly()
{
//return base.IsReadOnly();
return false;
}
[ConfigurationProperty("StationId")]
public string StationId { get { return base["StationId"].ToString(); } }
[ConfigurationProperty("MaxPga")]
public double MaxPga { get { return double.Parse(base["MaxPga"].ToString()); } set { base["MaxPga"] = value; } }
[ConfigurationProperty("MaxIntensity")]
public int MaxIntensity { get { return int.Parse(base["MaxIntensity"].ToString()); } set { base["MaxIntensity"] = value; } }
}接下來就是實際應用了,如果單純只是讀取的話,用Configuration.GetSection("") as CustomSection.接下來就可以用強型別讀取了.GetSection的參數是<section>裡name的值.如果要修改的話,就比較複雜一點.要用適當的層級(Level)去取得Configuration.然後設定強制Save.如下面的code
Configuration l_appcfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
MySection l_mySection = l_appcfg.GetSection("MyCustomSection") as MySection;
l_mySection.SectionInformation.ForceSave = true;
//用強型別修改你要修改的值...
l_appcfg.Save(ConfigurationSaveMode.Full);
ConfigurationManager.RefreshSection("MyCustomSection");修改完記得儲存和更新.