2013-03-01 46 views
2

我正在使用System.Configuration命名空間類型來存儲我的應用程序的配置。我需要將原始類型(System.Double)的集合存儲爲該配置的一部分。這似乎是矯枉過正創建以下內容:具有原始類型的ConfigurationElementCollection

[ConfigurationCollection(typeof(double), AddItemName="TemperaturePoint", 
    CollectionType=ConfigurationElementCollectionType.BasicMap)] 
class DoubleCollection : ConfigurationElementCollection 
{ 
    protected override ConfigurationElement CreateNewElement() 
    { 
     return // Do I need to create a custom ConfigurationElement that wraps a double? 
    } 

    protected override object GetElementKey(ConfigurationElement element) 
    { 
     return // Also not sure what to do here 
    } 
} 

我無法想象我是第一個遇到此問題的人。有任何想法嗎?

回答

3

我能得到這個沒有太多的定製工作。它類似於JerKimball的答案,但我避免使用ConfigurationProperty的TypeConverter屬性處理自定義字符串處理。

我的自定義配置部分實現:

using System.Configuration; 
using System.ComponentModel; 

class DomainConfig : ConfigurationSection 
{  

    [ConfigurationProperty("DoubleArray")] 
    [TypeConverter(typeof(CommaDelimitedStringCollectionConverter))] 
    public CommaDelimitedStringCollection DoubleArray 
    { 
     get { return (CommaDelimitedStringCollection)base["DoubleArray"]; } 
    } 
} 

它如何使用:

var doubleValues = from string item in configSection.DoubleArray select double.Parse(item); 

而且配置文件:

<DomainConfig DoubleArray="1.0,2.0,3.0"></DomainConfig> 
3

有沒有明確的「哎,我要的東西,在這裏值的列表」處理程序,但你有幾種選擇:

實現自定義IConfigurationSectionHandler和參考(比元素集合等方式簡單)通過:

<configSections> 
    <sectionGroup name="mysection" type="type of handler"/> 
</configSections> 

<mysection> 
    some xml representation of values 
</mysection> 

捎帶上現有的處理程序之一,像SingleTagSectionHandler - 這裏有一個毛茸茸的前瞻性一個襯墊,提取一組值在配置文件中此項:

<configuration> 
    <configSections> 
     <section name="TemperaturePoints" 
      type="System.Configuration.SingleTagSectionHandler" 
      allowLocation="true" 
      allowDefinition="Everywhere"/> 
    </configSections> 

    <TemperaturePoints values="1,2,3,4,5,6,7,8,9,10"/> 
</configuration> 


var values = ((string)((Hashtable)ConfigurationManager 
    .GetSection("TemperaturePoints"))["values"]) 
    .Split(',') 
    .Select(double.Parse); 

或分割了一下:

var section = (Hashtable)ConfigurationManager.GetSection("TemperaturePoints"); 
var packedValues = (string)section["values"]; 
var unpackedValues = packedValues.Split(','); 
var asDoubles = unpackedValues.Select(double.Parse).ToArray(); 
1

這是感覺我的權利的實現。

  • 在單獨的行的每個值(爲了便於差別)
  • 最小的開銷對於具有高信號的編碼噪聲

在底部設置限定解釋的簡單讀數。如果您想了解更多System.Configuration API的基礎知識,我推薦Jon Rista在CodeProject.com上的Unraveling the Mysteries of .NET 2.0 Configuration系列文章。

的app.config

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
     <section name="strings" 
       type="Sample.StringCollectionConfigSection, SampleAssembly"/> 
     <section name="databases" 
        type="Sample.StringCollectionConfigSection, SampleAssembly"/> 
    </configSections> 
    <strings> 
     <add>dbo.Foo</add> 
     <add>dbo.Bar</add> 
    </strings> 
    <databases> 
     <add>Development</add> 
     <add>Test</add> 
     <add>Staging</add> 
    </databases> 
</configuration> 

API使用

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (var s in StringCollectionConfigSection.Named("strings")) 
     { 
      Console.WriteLine(ignoreExpression); 
     } 
     foreach (var d in StringCollectionConfigSection.Named("strings")) 
     { 
      Console.WriteLine(ignoreExpression); 
     } 
    } 
} 

實現

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Xml; 

hnamespace Sample 
{ 
    public sealed class StringCollectionConfigSection : ConfigurationSection 
    { 
     public static StringElementCollection Named(string configSection) 
     { 
      var section = (StringCollectionConfigSection)ConfigurationManager.GetSection(configSection); 
      return section.Elements; 
     } 

     [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)] 
     public StringElementCollection Elements 
     { 
      get { return (StringElementCollection)base[""]; } 
      set { base[""] = value; } 
     } 
    } 

    [ConfigurationCollection(typeof(StringElement))] 
    public sealed class StringElementCollection : ConfigurationElementCollection, IEnumerable<string> 
    { 
     public StringElement this[int index] 
     { 
      get { return (StringElement)BaseGet(index); } 
      set 
      { 
       if (BaseGet(index) != null) { BaseRemoveAt(index); } 
       BaseAdd(index, value); 
      } 
     } 

     public new StringElement this[string key] 
     { 
      get { return (StringElement)BaseGet(key); } 
     } 

     protected override ConfigurationElement CreateNewElement() 
     { 
      return new StringElement(); 
     } 

     protected override object GetElementKey(ConfigurationElement element) 
     { 
      return ((StringElement)element).Value; 
     } 

     public new IEnumerator<string> GetEnumerator() 
     { 
      var enumerator = base.GetEnumerator(); 
      while (enumerator.MoveNext()) 
      { 
       yield return ((StringElement)enumerator.Current).Value; 
      } 
     } 
    } 

    public class StringElement : ConfigurationElement 
    { 
     protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey) 
     { 
      Value = (string)reader.ReadElementContentAs(typeof(string), null); 
     } 

     public string Value {get; private set; } 
    } 
} 

學習POI關於代碼的nts。

  • 在app.config中,確保在定義配置節的名稱時使用名稱空間和程序集名稱。
  • 我不想要我的收藏中額外的子元素。我只想要包含字符串值的元素。
    • 上的StringCollectionConfigSectionStringElementCollection Elements屬性定義的ConfigurationPropertyAttribute使用空名稱來完成的默認收集風格,我想實現的。

<strings> 
    <elements> 
     <add>...</add> 
     <add>...</add> 
    <elements> 
</strings> 
  • DeserializeElementStringElement允許我使用的XmlNode作爲價值的innerText,而不是一個屬性。

  • ConfigurationElementCollection加上StringElementCollection Named(string configSection)StringCollectionConfigSectionIEnumerator<string>給我的乾淨的API,我想。