2011-08-26 7 views
9

¡Mi cabeza está golpeando absolutamente mal! He hecho esto antes, pero no tan "en profundidad" ni tan complejo como este, y he intentado diferentes maneras de hacerlo posible, pero todo ha fallado.Configuración personalizada para app.config - colecciones de secciones?

Por lo tanto, este es el XML personalizado que quiero en el app.config:

<Profiles> <!--Collection--> 
<Profile Name="Live"> 
    <Components> 
    <Component Name="Portal" Type="Web" /> 
    <Component Name="Comms" Type="Web" /> 
    <Component Name="Scheduler" Type="WindowsService" ServiceName="LiveScheduler" /> 
    </Components> 
    <Databases> 
    <Database Name="Main" Connection="Data Source=.\SQL2008" /> 
    <Database Name="Staging" Connection="Data Source=SomeSite.co.uk" /> 
    </Databases> 
</Profile> 
<Profile Name="Test"> 
    <Components> 
    <Component Name="Portal" Type="Web" /> 
    <Component Name="Comms" Type="Web" /> 
    <Component Name="Scheduler" Type="WindowsService" ServiceName="TestScheduler" /> 
    </Components> 
    <Databases> 
    <Database Name="Main" Connection="Data Source=.\SQL2008" /> 
    <Database Name="Staging" Connection="Data Source=Internal" /> 
    </Databases> 
</Profile> 
</Profiles> 

Así que una colección de perfil con cada perfil que tiene una colección de sub-elementos (Components es una colección, a continuación, componente es una elemento)

Sin embargo, actualmente tengo todo eso EXCEPTO para los perfiles múltiples. De alguna manera veo el problema, pero no estoy seguro de cómo "arreglarlo".

Código:

public class Profile : ConfigurationSection 
{ 
    [ConfigurationProperty("Name", IsRequired=true)] 
    public string Name 
    { 
     get 
     { 
      return base["Name"] as string; 
     } 
      set 
      { 
       base["Name"] = value; 
      } 
     } 

     [ConfigurationProperty("Components")] 
     public ComponentCollection Components 
     { 
      get { return ((ComponentCollection)(base["Components"])); } 
     } 

     [ConfigurationProperty("Databases")] 
     public DatabaseCollection Databases 
     { 
      get 
      { 
       return ((DatabaseCollection)(base["Databases"])); 
      } 
     } 
    } 

    [ConfigurationCollection(typeof(Component), AddItemName="Component")] 
    public class ComponentCollection : ConfigurationElementCollection 
    {   
     protected override ConfigurationElement CreateNewElement() 
     { 
      return new Component(); 
     } 

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

     public Component this[int idx] 
     { 
      get 
      { 
       return base.BaseGet(idx) as Component; 
      } 
      set 
      { 
       if (base.BaseGet(idx) != null) 
       { 
        base.BaseRemoveAt(idx); 
       } 
       this.BaseAdd(idx, value); 
      } 
     } 

     public Component this[string key] 
     { 
      get 
      { 
       return base.BaseGet(key) as Component; 
      } 
      set 
      { 
       if (base.BaseGet(key) != null) 
       { 
        base.BaseRemove(key); 
       } 
       this.BaseAdd(this.Count, value); 
      } 
     } 
    } 

    public class Component : ConfigurationElement 
    { 
     [ConfigurationProperty("Type", IsRequired = true)] 
     public string Type 
     { 
      get 
      { 
       return this["Type"] as string; 
      } 
      set 
      { 
       this["Type"] = value; 
      } 
     } 

     [ConfigurationProperty("Name", IsRequired = true, IsKey = true)] 
     public string Name 
     { 
      get 
      { 
       return this["Name"] as string; 
      } 
      set 
      { 
       this["Name"] = value; 
      } 
     } 

     [ConfigurationProperty("ServiceName", IsRequired = false)] 
     public string ServiceName 
     { 
      get 
      { 
       return this["ServiceName"] as string; 
      } 
      set 
      { 
       this["ServiceName"] = value; 
      } 
     } 
    } 

    [ConfigurationCollection(typeof(Database), AddItemName = "Database")] 
    public class DatabaseCollection : ConfigurationElementCollection 
    { 
     protected override ConfigurationElement CreateNewElement() 
     { 
      return new Database(); 
     } 

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


     public Database this[int idx] 
     { 
      get 
      { 
       return base.BaseGet(idx) as Database; 
      } 
      set 
      { 
       if (base.BaseGet(idx) != null) 
       { 
        base.BaseRemoveAt(idx); 
       } 
       this.BaseAdd(idx, value); 
      } 
     } 

     public Database this[string key] 
     { 
      get 
      { 
       return base.BaseGet(key) as Database; 
      } 
      set 
      { 
       if (base.BaseGet(key) != null) 
       { 
        base.BaseRemove(key);; 
       } 

       this.BaseAdd(this.Count, value); 
      } 
     } 
    } 

    public class Database : ConfigurationElement 
    { 
     [ConfigurationProperty("Name", IsKey = true, IsRequired = true)] 
     public string Name 
     { 
      get 
      { 
       return this["Name"] as string; 
      } 
      set 
      { 
       this["Name"] = value; 
      } 
     } 

     [ConfigurationProperty("Connection", IsKey = false, IsRequired = true)] 
     public string Connection 
     { 
      get 
      { 
       return this["Connection"] as string; 
      } 
      set 
      { 
       this["Connection"] = value; 
      } 
     } 
    } 
+1

Parece que está intentando tener diferentes perfiles para diferentes entornos, ¿por qué no nos fijamos en la extensión del guepardo lenta para VS, que fue lanzado esta semana. Hace prácticamente lo que quiere: http://www.sadev.co.za/content/appconfig-transformations-community-shines-where-microsoft-drops-ball –

+0

¿Alguna información sobre el problema con el código? – Jodrell

Respuesta

0

Usted está aplicando correctamente, excepto que necesita un nivel extra. Cambie el perfil de una sección de configuración a un elemento de configuración, luego cree un perfil de sección de configuración que contenga una colección de elementos de perfil.

Este es un excelente caso para pruebas automatizadas, sin errores de configuración de secciones de configuración.

+0

Gracias a todos por sus respuestas hasta el momento. La extensión de Cheetah se ve interesante. –

+0

woops ... presiona entrar demasiado rápido. ssamuel: creo que intenté tu enfoque antes, pero no llegué a ningún lado, salvo excepciones que arrojaron diciendo que necesita implementar IConfigurationSectionHandler. Veré si puedo hacer esto de nuevo. Pero me pregunto si es más rápido serializar/deserializar un objeto en XML y usarlo para ser honesto: -/ –

+0

Ugh, ¿qué versión del FW estás usando? IConfigurationSectionHandler está en desuso después de 2.0. Si todavía está buscando, [intente esto] (http://msdn.microsoft.com/en-us/library/2tw134k3.aspx). Serialize-to-XML es más rápido e intuitivo. Escribir en la configuración es más bonito. Depende de dónde quiera dejar la dificultad de mantenimiento, en el administrador del sistema o el desarrollador. – ssamuel

7

Necesita mover su sección de configuración un nivel más alto.

public class Profiles : ConfigurationSection 
{ 
    [ConfigurationProperty("Profile")] 
    public ProfileCollection Profile 
    { 
     get 
     { 
      return this["profile"] as ProfileCollection; 
     } 
    } 
}  

Aquí hay una sección que he creado. Usted debe ser capaz de conseguir el suyo trabaja siguiendo este:

public class ImportConfiguration : ConfigurationSection 
{ 
    [ConfigurationProperty("importMap")] 
    public ImportMapElementCollection ImportMap 
    { 
     get 
     { 
      return this["importMap"] as ImportMapElementCollection; 
     } 
    } 
} 

public class ImportColumnMapElement : ConfigurationElement 
{ 
    [ConfigurationProperty("localName", IsRequired = true, IsKey = true)] 
    public string LocalName 
    { 
     get 
     { 
      return this["localName"] as string; 
     } 
     set 
     { 
      this["localName"] = value; 
     } 
    } 

    [ConfigurationProperty("sourceName", IsRequired = true)] 
    public string SourceName 
    { 
     get 
     { 
      return this["sourceName"] as string; 
     } 
     set 
     { 
      this["sourceName"] = value; 
     } 
    } 
} 

public class ImportMapElementCollection : ConfigurationElementCollection 
{ 
    public ImportColumnMapElement this[object key] 
    { 
     get 
     { 
      return base.BaseGet(key) as ImportColumnMapElement; 
     } 
    } 

    public override ConfigurationElementCollectionType CollectionType 
    { 
     get 
     { 
      return ConfigurationElementCollectionType.BasicMap; 
     } 
    } 

    protected override string ElementName 
    { 
     get 
     { 
      return "columnMap"; 
     } 
    } 

    protected override bool IsElementName(string elementName) 
    { 
     bool isName = false; 
     if (!String.IsNullOrEmpty(elementName)) 
      isName = elementName.Equals("columnMap"); 
     return isName; 
    } 

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

    protected override object GetElementKey(ConfigurationElement element) 
    { 
     return ((ImportColumnMapElement)element).LocalName; 
    } 
} 
Cuestiones relacionadas