2012-01-12 15 views
25

per la configurazione come seguecome disporre di un attributo personalizzato in ConfigurationElementCollection?

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

quando implementare una MyCollection, che cosa devo fare per il "default" attributo?

+0

controllo questo fuori: https://stackoverflow.com/questions/43037691/design-to-implement-a-wrapper-for-configurationsection-net-class –

risposta

49

Supponiamo di avere questo file 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> 

Poi, con questo codice:

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"]; 
     } 
    } 
} 

è possibile leggere la configurazione con l'attributo 'default', in questo modo:

Questo emetterà "uno"

+1

AddItemName = "entry", che è esattamente ciò che Voglio! – Xinan

5

Non so se sia possibile avere un valore predefinito in ConfigurationElementCollection. (non sembra avere alcuna proprietà per il valore predefinito).

Immagino che tu debba implementarlo da solo. Guarda l'esempio qui sotto.

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; } 
    } 
} 

Ecco la configurazione XML:

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

E poi, il codice, si accede alla voce predefinita utilizzando il seguente:

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

Naturalmente, la classe MyConfig può nascondere i dettagli di accesso alle proprietà Repository e CurrentRepository. È possibile avere una proprietà denominata DefaultRepository (di tipo Repository) nella classe MyConfig per restituirlo.

0

Se si vuole genericize esso, questo dovrebbe aiutare:

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); 
    } 
    } 
} 

Ecco l'interfaccia di cui sopra:

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

questo può essere un po 'tardi, ma può essere utile agli altri.

È possibile ma con alcune modifiche.

  • ConfigurationElementCollection eredita ConfigurationElement come "questa [stringa]" è disponibile in ConfigurationElement.

  • Generalmente quando ConfigurationElementCollection viene ereditata e implementata in un'altra classe, "questa [stringa]" è nascosta con "nuova questa [stringa]".

  • Un modo per aggirare l'ostacolo è quello di creare un altro attuazione del presente [] come "questo [String, String]"

Si veda l'esempio qui sotto.

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; } 
    } 
}