Hasta el momento hemos tocado la creación de configuraciones personalizadas, elementos de configuración personalizados y la creación de grupos de secciones de configuración personalizados. Es interesante pero eso simplemente es la punta del iceberg de todo lo que dentro del concepto de configuración que nos permite manejar o mover la .NET Framework, hoy profundizaremos un poco más acerca de agregar nuevas características a nuestra configuración personalizada.
Colecciones y listas
Se que muchos hemos visto secciones de la configuración de ASP.NET y notado el uso de colecciones en él web.config, por ejemplo, el segmento de appSettings:
<appSettings>
<clear />
<remove name="port" />
<add name="port" value="81" />
</appSettings>
Luego acceder a tal segmento de la configuración es "relativamente" sencillo, basta con algo como esto:
int port = int.Parse(ConfigurationManager.AppSettings["port"]);
Como habrán notado esto nos permite tener secciones que se comportan como colecciones de valores, que luego pueden ser accedidas por un indexer usando el nombre (en este caso "port") o el índice (en este caso, 0). Estas colecciones también soportan operaciones básicas (remove, clear, add). Crear colecciones de valores para la configuración no es para nada difícil simplemente hay que heredar de una clase abstracta especial, ConfigurationElementCollection
Comencemos por la unidad mínima, digamos que son elementos para datos de servidores
using System.Configuration;
namespace Samples {
public class ServerConfigurationElement : ConfigurationElement {
[ConfigurationProperty("name", IsRequired = true)]
public string Name {
get { return (string) this["name"]; }
}
[ConfigurationProperty("port", DefaultValue = 80)]
public int Port {
get { return (int) this["port"]; }
}
[ConfigurationProperty("host", IsRequired = true)]
public string Host {
get { return (string) this["host"]; }
}
}
}
Hasta el momento nada diferente de lo que conocemos. Ahora agreguemos el soporte para la colección de elementos de configuración tipo ServerConfigurationElement
using System.Configuration;
namespace Samples {
[ConfigurationCollection(typeof(ServerConfigurationElement))]
public class ServerConfigurationCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() {
return new ServerConfigurationElement();
}
protected override object GetElementKey(ConfigurationElement element) {
var value = element as ServerConfigurationElement;
return value != null ? value.Name : null;
}
public ServerConfigurationElement this[int index] {
get {
return BaseGet(index) as ServerConfigurationElement;
}
set {
if (BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
public new ServerConfigurationElement this[string name] {
get {
return BaseGet(name) as ServerConfigurationElement;
}
}
}
}
Obligatoriamente tenemos que implementar los métodos CreateNewElement (el cual creo su nombre e implementación son suficientemente descriptivos) y el método GetElementKey, este nos retorna el valor que tendrá la key del diccionario de elementos. Observen como implementamos los indexers que luego necesitaremos para acceder a los elementos de la colección. Nótese también que nuestra colección esta adornada con el atributo ConfigurationCollectionAttribute, el cual no es estrictamente necesario.
Bien, nos queda simplemente implementar la sección de configuración general, no muy diferente
using System.Configuration;
namespace Samples {
public class SampleConfigurationSection : ConfigurationSection {
[ConfigurationProperty("default", IsRequired = true)]
public string DefaultServer {
get { return (string) this["default"]; }
}
[ConfigurationProperty("servers", IsRequired = true)]
public ServerConfigurationCollection Servers {
get {
return this["servers"]
as ServerConfigurationCollection;
}
}
}
}
Nuestra configuración personalizada lucirá algo así:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="sample"
type="Samples.SampleConfigurationSection, Samples.Cfg"/>
</configSections>
<sample default="default">
<servers>
<clear />
<add name="default" host="localhost" />
<add name="another" port="8080" host="192.168.1.1" />
</servers>
</sample>
</configuration>
Y en nuestro programa podemos acceder a ella de forma sencilla
using System;
using System.Configuration;
namespace Samples {
internal class Program {
private static void Main(string[] args) {
var cfg = ConfigurationManager.GetSection("sample") as SampleConfigurationSection;
if (cfg == null) return;
Console.WriteLine("Default item: {0}", cfg.DefaultServer);
foreach (ServerConfigurationElement server in cfg.Servers) {
Console.WriteLine("server: {0}, host: {1}, port: {2}",
server.Name, server.Host, server.Port);
}
ServerConfigurationElement defaultServer = cfg.Servers[cfg.DefaultServer];
Console.WriteLine("Default host: {0}", defaultServer.Host);
Console.ReadLine();
}
}
}
Como les advertí desde el principio, nada complicado y sumamente útil. Creo que vale la pena mencionar que cualquier comentario, sugerencia, duda u observación soy todo ojos para leer sus comentarios.
Cómo dijo Terminator, volveré…
Pingback: Tweets that mention .NET y Configuraciones – Parte 4 | IDisposable Thoughts -- Topsy.com
Pingback: .NET y Configuraciones – Parte 5 | IDisposable Thoughts
Pingback: .NET y configuraciones – Parte 1 | IDisposable Thoughts