Si está buscando una sección de configuración personalizada como la siguiente
<CustomApplicationConfig>
<Credentials Username="itsme" Password="mypassword"/>
<PrimaryAgent Address="10.5.64.26" Port="3560"/>
<SecondaryAgent Address="10.5.64.7" Port="3570"/>
<Site Id="123" />
<Lanes>
<Lane Id="1" PointId="north" Direction="Entry"/>
<Lane Id="2" PointId="south" Direction="Exit"/>
</Lanes>
</CustomApplicationConfig>
entonces puedes usar mi implementación de la sección de configuración para comenzar a agregar una System.Configuration
referencia de ensamblaje a tu proyecto
Mire cada uno de los elementos anidados que utilicé, el primero es Credenciales con dos atributos, así que agreguemos primero
Elemento de credenciales
public class CredentialsConfigElement : System.Configuration.ConfigurationElement
{
[ConfigurationProperty("Username")]
public string Username
{
get
{
return base["Username"] as string;
}
}
[ConfigurationProperty("Password")]
public string Password
{
get
{
return base["Password"] as string;
}
}
}
Agente primario y Agente secundario
Ambos tienen los mismos atributos y parecen una Dirección a un conjunto de servidores para una conmutación por error primaria y, por lo que solo necesita crear una clase de elemento para ambos, como los siguientes
public class ServerInfoConfigElement : ConfigurationElement
{
[ConfigurationProperty("Address")]
public string Address
{
get
{
return base["Address"] as string;
}
}
[ConfigurationProperty("Port")]
public int? Port
{
get
{
return base["Port"] as int?;
}
}
}
Explicaré cómo usar dos elementos diferentes con una clase más adelante en esta publicación, omita el SiteId ya que no hay diferencia en él. Solo tiene que crear una clase igual que la anterior con una sola propiedad. veamos cómo implementar la colección Lanes
se divide en dos partes, primero debe crear una clase de implementación de elemento y luego crear una clase de elemento de colección
LaneConfigElement
public class LaneConfigElement : ConfigurationElement
{
[ConfigurationProperty("Id")]
public string Id
{
get
{
return base["Id"] as string;
}
}
[ConfigurationProperty("PointId")]
public string PointId
{
get
{
return base["PointId"] as string;
}
}
[ConfigurationProperty("Direction")]
public Direction? Direction
{
get
{
return base["Direction"] as Direction?;
}
}
}
public enum Direction
{
Entry,
Exit
}
puede notar que un atributo de LanElement
es una Enumeración y si intenta usar cualquier otro valor en la configuración que no esté definido en la aplicación Enumeración arrojará un System.Configuration.ConfigurationErrorsException
inicio. Ok, pasemos a la definición de colección
[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class LaneConfigCollection : ConfigurationElementCollection
{
public LaneConfigElement this[int index]
{
get { return (LaneConfigElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(LaneConfigElement serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new LaneConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((LaneConfigElement)element).Id;
}
public void Remove(LaneConfigElement serviceConfig)
{
BaseRemove(serviceConfig.Id);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(String name)
{
BaseRemove(name);
}
}
puedes notar que he configurado el AddItemName = "Lane"
puedes elegir lo que quieras para el elemento de entrada de tu colección, prefiero usar "agregar" el predeterminado pero lo cambié solo por el bien de esta publicación.
Ahora todos nuestros elementos anidados se han implementado, ahora debemos agregar todos los de una clase que tiene que implementar System.Configuration.ConfigurationSection
CustomApplicationConfigSection
public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
{
private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
public const string SECTION_NAME = "CustomApplicationConfig";
[ConfigurationProperty("Credentials")]
public CredentialsConfigElement Credentials
{
get
{
return base["Credentials"] as CredentialsConfigElement;
}
}
[ConfigurationProperty("PrimaryAgent")]
public ServerInfoConfigElement PrimaryAgent
{
get
{
return base["PrimaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("SecondaryAgent")]
public ServerInfoConfigElement SecondaryAgent
{
get
{
return base["SecondaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("Site")]
public SiteConfigElement Site
{
get
{
return base["Site"] as SiteConfigElement;
}
}
[ConfigurationProperty("Lanes")]
public LaneConfigCollection Lanes
{
get { return base["Lanes"] as LaneConfigCollection; }
}
}
Ahora puede ver que tenemos dos propiedades con nombre PrimaryAgent
y SecondaryAgent
ambas tienen el mismo tipo. Ahora puede comprender fácilmente por qué solo teníamos una clase de implementación para estos dos elementos.
Antes de poder utilizar esta sección de configuración recién inventada en su app.config (o web.config) solo necesita decirle a la aplicación que ha inventado su propia sección de configuración y darle un poco de respeto, para ello debe agregar las siguientes líneas en app.config (puede ser justo después del inicio de la etiqueta raíz).
<configSections>
<section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
</configSections>
NOTA: MyAssemblyName debe estar sin .dll, por ejemplo, si el nombre del archivo de ensamblado es myDll.dll, use myDll en lugar de myDll.dll
para recuperar esta configuración, use la siguiente línea de código en cualquier lugar de su aplicación
CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;
Espero que la publicación anterior lo ayude a comenzar con un tipo un poco complicado de secciones de configuración personalizadas.
Happy Coding :)
**** Editar **** Para habilitar LINQ en LaneConfigCollection
tienes que implementarIEnumerable<LaneConfigElement>
Y agregue la siguiente implementación de GetEnumerator
public new IEnumerator<LaneConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as LaneConfigElement;
}
}
para las personas que todavía están confundidas acerca de cómo funciona realmente el rendimiento, lea este bonito artículo
Dos puntos clave tomados del artículo anterior son
en realidad no termina la ejecución del método. return return detiene la ejecución del método y la próxima vez que lo llame (para el siguiente valor de enumeración), el método continuará ejecutándose desde la última llamada de return. Suena un poco confuso, creo ... (Shay Friedman)
El rendimiento no es una característica del tiempo de ejecución .Net. Es solo una característica del lenguaje C # que el compilador C # compila en código IL simple. (Lars Corneliussen)