雖然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");
修改完記得儲存和更新.