2012-01-12 15 views
25

的配置如下如何在ConfigurationElementCollection中擁有自定義屬性?

<MyCollection default="one"> 
    <entry name="one" ... other attrubutes /> 
    ... other entries 
</MyCollection> 

時實現MyCollection的,我應該爲「默認」做屬性?

+0

檢查了這一點: https://stackoverflow.com/questions/43037691/design-to-implement-a-wrapper-for-configurationsection-net-class – 2017-10-26 04:16:56

回答

49

讓我們假設你有這樣的config文件:

<configuration> 
    <configSections> 
     <section name="mySection" type="ConsoleApplication1.MySection, ConsoleApplication1" /> // update type & assembly names accordingly 
    </configSections> 

    <mySection> 
     <MyCollection default="one"> 
      <entry name="one" /> 
      <entry name="two" /> 
     </MyCollection> 
    </mySection> 
</configuration> 

然後,使用此代碼:

public class MySection : ConfigurationSection 
{ 
    [ConfigurationProperty("MyCollection", Options = ConfigurationPropertyOptions.IsRequired)] 
    public MyCollection MyCollection 
    { 
     get 
     { 
      return (MyCollection)this["MyCollection"]; 
     } 
    } 
} 

[ConfigurationCollection(typeof(EntryElement), AddItemName = "entry", CollectionType = ConfigurationElementCollectionType.BasicMap)] 
public class MyCollection : ConfigurationElementCollection 
{ 
    protected override ConfigurationElement CreateNewElement() 
    { 
     return new EntryElement(); 
    } 

    protected override object GetElementKey(ConfigurationElement element) 
    { 
     if (element == null) 
      throw new ArgumentNullException("element"); 

     return ((EntryElement)element).Name; 
    } 

    [ConfigurationProperty("default", IsRequired = false)] 
    public string Default 
    { 
     get 
     { 
      return (string)base["default"]; 
     } 
    } 
} 

public class EntryElement : ConfigurationElement 
{ 
    [ConfigurationProperty("name", IsRequired = true, IsKey = true)] 
    public string Name 
    { 
     get 
     { 
      return (string)base["name"]; 
     } 
    } 
} 

您可以用 '默認' 屬性讀取配置,如下所示:

MySection section = (MySection)ConfigurationManager.GetSection("mySection"); 
    Console.WriteLine(section.MyCollection.Default); 

這將輸出「one」

+1

AddItemName = 「項」,這正是我想要! – Xinan 2014-09-30 06:35:14

5

我不知道是否有可能在ConfigurationElementCollection中具有默認值。 (它沒有看到任何屬性的默認值)。

我想你必須自己實現這個。看下面的例子。

public class Repository : ConfigurationElement 
{ 
    [ConfigurationProperty("key", IsRequired = true)] 
    public string Key 
    { 
     get { return (string)this["key"]; } 
    } 

    [ConfigurationProperty("value", IsRequired = true)] 
    public string Value 
    { 
     get { return (string)this["value"]; } 
    } 
} 

public class RepositoryCollection : ConfigurationElementCollection 
{ 
    protected override ConfigurationElement CreateNewElement() 
    { 
     return new Repository(); 
    } 

    protected override object GetElementKey(ConfigurationElement element) 
    { 
     return (element as Repository).Key; 
    } 

    public Repository this[int index] 
    { 
     get { return base.BaseGet(index) as Repository; } 
    } 

    public new Repository this[string key] 
    { 
     get { return base.BaseGet(key) as Repository; } 
    } 

} 

public class MyConfig : ConfigurationSection 
{ 
    [ConfigurationProperty("currentRepository", IsRequired = true)] 
    private string InternalCurrentRepository 
    { 
     get { return (string)this["currentRepository"]; } 
    } 

    [ConfigurationProperty("repositories", IsRequired = true)] 
    private RepositoryCollection InternalRepositories 
    { 
     get { return this["repositories"] as RepositoryCollection; } 
    } 
} 

這裏的XML配置:

<myConfig currentRepository="SQL2008"> 
    <repositories> 
     <add key="SQL2008" value="abc"/> 
     <add key="Oracle" value="xyz"/> 
    </repositories> 
    </myConfig> 

,然後在你的代碼,您使用以下訪問默認項:

MyConfig conf = (MyConfig)ConfigurationManager.GetSection("myConfig"); 
string myValue = conf.Repositories[conf.CurrentRepository].Value; 

當然,的myconfig類可以隱藏訪問Repositories和CurrentRepository屬性的詳細信息。您可以在MyConfig類中擁有一個名爲DefaultRepository(類型爲Repository)的屬性來返回該屬性。

0

如果你想泛化它,這應該幫助:

using System.Configuration; 

namespace Abcd 
{ 
    // Generic implementation of ConfigurationElementCollection. 
    [ConfigurationCollection(typeof(ConfigurationElement))] 
    public class ConfigurationElementCollection<T> : ConfigurationElementCollection 
             where T : ConfigurationElement, IConfigurationElement, new() 
    { 
    protected override ConfigurationElement CreateNewElement() 
    { 
     return new T(); 
    } 

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

    public T this[int index] 
    { 
     get { return (T)BaseGet(index); } 
    } 

    public T GetElement(object key) 
    { 
     return (T)BaseGet(key); 
    } 
    } 
} 

這裏是上面提到的接口:

namespace Abcd 
{ 
    public interface IConfigurationElement 
    { 
    object GetElementKey(); 
    } 
} 
1

這可能有點遲,但可能會有所幫助別人。

這是可能的,但有一些修改。

  • ConfigurationElementCollection繼承了ConfigurationElement,因爲「this [string]」在ConfigurationElement中可用。

  • 通常,當ConfigurationElementCollection被繼承並在另一個類中實現時,「this [string]」會被隱藏,並帶有「new this [string]」。

  • 一種方法來解決它是創造這個[],如「此[字符串,字符串]」的另一種實現

見下面的例子。

public class CustomCollection : ConfigurationElementCollection 
{ 
    protected override ConfigurationElement CreateNewElement() 
    { 
     return new CustomElement(); 
    } 

    protected override object GetElementKey(ConfigurationElement element) 
    { 
     return ((CustomElement)element).Name; 
    } 

    public CustomElement this[int index] 
    { 
     get { return (CustomElement)base.BaseGet(index); } 
     set 
     { 
      if (BaseGet(index) != null) 
       BaseRemoveAt(index); 

      BaseAdd(index, value); 
     } 
    } 

    // ConfigurationElement this[string] now becomes hidden in child class 
    public new CustomElement this[string name] 
    { 
     get { return (CustomElement)BaseGet(name); } 
    } 

    // ConfigurationElement this[string] is now exposed 
    // however, a value must be entered in second argument for property to be access 
    // otherwise "this[string]" will be called and a CustomElement returned instead 
    public object this[string name, string str = null] 
    { 
     get { return base[name]; } 
     set { base[name] = value; } 
    } 
}