當需存放多筆「數值」於 app.config 中時,最簡單的作法就是使用特殊符號將字串分開,後續再從程式碼中以切割字串方式轉換為陣列;但有時會需要存放「物件形式」陣列資料,例如設定單筆伺服器可能就會包含名稱、位置、參數等資訊,而此時就可以透過自定義 ConfigurationSection 來實現。
情境說明
筆者想建立一支監看各資料夾資料變動情況的應用程式,希望讓使用者自行增減多組資料夾設定,分別歸類在 indoor 及 outdoor 兩個集合中,其中需提供「名稱」、「路徑位置」及「啟用狀態」三項資料夾資訊, 而預期目標就是要將所有設定放至 app.config 中,因此預計在 app.config 中會以下圖方式設定配置,而實際做法請參考以下說明。
- ConfigurationElement 物件
- ConfigurationElementCollection 物件
- ConfigurationSection 物件
建立 ConfigurationElement 物件
建立繼承自 ConfigurationElement
的 FolderElement 物件,可依照所需存放的「資訊」來建立屬性 。
public class FolderElement : ConfigurationElement
{
// 資料夾名稱
[ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base["name"]; }
set { base["name"] = value; }
}
// 資料夾路徑
[ConfigurationProperty("path", DefaultValue = "", IsKey = false, IsRequired = true)]
public string Path
{
get { return (string)base["path"]; }
set { base["path"] = value; }
}
// 是否啟用
[ConfigurationProperty("isActive", DefaultValue = "true", IsKey = false, IsRequired = false)]
public bool IsActive
{
get { return (bool)base["isActive"]; }
set { base["isActive"] = value; }
}
}
建立 ConfigurationElementCollection 物件
建立繼承自 ConfigurationElementCollection
的 FolderCollection 物件,指定使用 <folder> 標籤作為 app.config 中 element 名稱 ,並使用 FolderElement 來 override 各所需方法。
[ConfigurationCollection(typeof(FolderElement))]
public class FolderCollection : ConfigurationElementCollection
{
// 設定 app.config 中 collection 的 element 標籤為 <folder>
internal const string _propertyName = "folder";
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMapAlternate;
}
}
protected override bool IsElementName(string elementName)
{
return elementName.Equals(_propertyName, StringComparison.InvariantCultureIgnoreCase);
}
protected override ConfigurationElement CreateNewElement()
{
return new FolderElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((FolderElement)(element)).Name;
}
}
建立 ConfigurationSection 物件
建立繼承自 ConfigurationSection
的 FolderCollection 物件,依照需求建立所需集合屬性;在此建立 IndoorFolderCollection 及 OutdoorFolderCollection 屬性,並分別指定使用 <IndoorFolders> 及 <OutdoorFolders> 標籤於 app.config 中表示各集合組態區塊。
public class FolderSection : ConfigurationSection
{
// 定義 app.config 中此 section 所使用的 collection 標籤為 <indoorFolders>
[ConfigurationProperty("indoorFolders")]
public FolderCollection IndoorFolderCollection
{
get { return ((FolderCollection)(base["indoorFolders"])); }
set { base["indoorFolders"] = value; }
}
// 定義 app.config 中此 section 所使用的 collection 標籤為 <outdoorFolders>
[ConfigurationProperty("outdoorFolders")]
public FolderCollection OutdoorFolderCollection
{
get { return ((FolderCollection)(base["outdoorFolders"])); }
set { base["outdoorFolders"] = value; }
}
}
設定 app.config
最後在 app.config 中建立 configSections 區塊,可於此定義多組 Section 並明確標示名稱及型態 (full class name, assembly name),接著就可以在下方使用相同名稱建立 section 內容。
<configuration>
<!-- Config Sections -->
<configSections>
<!-- type = full section class name, assembly name -->
<section name="folderSection"
type="Sample.FileCleaner.CustomerConfig.FolderSection, Sample.FileCleaner"/>
</configSections>
<!-- Customer Section -->
<folderSection>
<indoorFolders>
<folder name="內網-圖片"
path="\InFileServer\Photo"
isActive="true"/>
<folder name="內網-影片"
path="\InFileServer\Video"
isActive="true"/>
</indoorFolders>
<outdoorFolders>
<folder name="外網-圖片"
path="\OutFileServer\Photo"
isActive="true"/>
<folder name="外網-影片"
path="\OutFileServer\Video"
isActive="true"/>
</outdoorFolders>
</folderSection>
<!-- 略 -->
</configuration>
取出資料
可以先建立一個 ConfigSetting 類別,以此統一處理向 app.config 取值的作業;以下就是透過 FolderSection
- FolderCollection
- FolderElement
關係,依序找到我們所記載在 app.config 的資料。
public class ConfigSetting
{
// 取得 FolderSection
private static FolderSection _folderSection =
ConfigurationManager.GetSection("folderSection") as FolderSection;
// 取得 FolderSection - IndoorFolderCollection - FolderElements
public static IEnumerable<FolderElement> GetMonitorIndoorFolders()
{
var folderCollection = _folderSection.IndoorFolderCollection;
foreach (FolderElement folder in folderCollection)
{
if (folder != null)
yield return folder;
}
}
// 取得 FolderSection - OutdoorFolderCollection - FolderElements
public static IEnumerable<FolderElement> GetMonitorOutdoorFolders()
{
var folderCollection = _folderSection.OutdoorFolderCollection;
foreach (FolderElement folder in folderCollection)
{
if (folder != null)
yield return folder;
}
}
}
來看看取得的資料
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"====== 【Indoor Folders】=======");
ShowFolders(ConfigSetting.GetMonitorIndoorFolders());
Console.WriteLine($"=======【Outdoor Folders】=======");
ShowFolders(ConfigSetting.GetMonitorOutdoorFolders());
Console.Read();
}
public static void ShowFolders(IEnumerable<FolderElement> folders)
{
foreach (var folder in folders)
{
Console.WriteLine($"Name: {folder.Name}");
Console.WriteLine($"Path: {folder.Path}");
Console.WriteLine($"IsActive: {folder.IsActive}");
Console.WriteLine($"--");
}
}
}
順利將資料通通取出囉!
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !