domingo, 31 de julio de 2011

Archivos de Configuración - Una introducción (1/3)

 

Introducción

Es muy común tener que definir parámetros en las aplicaciones que se desarrollan proporcionando cierta configuración que si bien se podría considerar casi estática (porque no cambia constantemente), si sea necesario prever la posibilidad de adaptación.

Un ejemplo muy claro de estos es la cadena de conexión a la base de datos, por lo general una vez instalada la aplicación no cambia, pero cuando se esta en la etapa de implementación seguramente sea necesario su adaptación al entorno.

Por lo general se busca que sea un lugar que impacte lo menos posible en el desarrollo, algunos tienden a crear una clase y colocar constantes o variables readonly dentro del propio código, pero el problema con esto es que requieren recompilar por completo el desarrollo, además de tener que actualizar cada cliente por un simple cambio de configuración.

También se busca un lugar estándar y conocido, algunos usan la registry de windows para definir configuración, quizás era una opción se algo mas viable cuando se contaba con Win XP, pero con Sistemas Operativos como ser Vista o Win 7 esto cambio bastante, el modelo de seguridad que estos imponen aplica restricciones a estas acciones, no haciendo tan cómoda la escritura en este sitio.

Entonces porque no usar la propuesta que hace .net al respecto, si se trata de los archivos de configuración, entre las ventajas que este presenta se pueden encontrar:

  • una lectura simple, ya que se basa en xml
  • fácil acceso y modificación (se puede editar con el notepad), por lo general este archivo se encuentra junto a la aplicación por lo que la seguridad debería permitir la escritura en esta carpeta

Entre los temas que se trataran en este articulo

1- Agregar un archivo de configuración a nuestro proyecto

2- Definir una sección key-value

2a- usando la sección appSettings

2b- definiendo una sección propia

 

1- Agregar un archivo de configuración a nuestro proyecto

Si bien es una acción sencilla, si recién se esta introduciendo en el desarrollo, puede que no resulte tan intuitivo encontrar los pasos para agregar un archivo de configuración.

Estando sobre el proyecto en el “Solution Explorer”, se acciona el menú que aparece con el boton derecho del mouse, seleccionado el menu Add –> New Item…

en el recuadro se seleccionara la opción:

Esto agregar un archivo de nombre App.config, que en una primer instancia tendrá solo un tag.

Empecemos por una tarea simple, la lectura de una cadena de conexión.

Para lograr esta tarea se necesitara la ayuda de una clase en particular, me refiero al 

ConfigurationManager

con esta clase tendremos acceso a los tag de información definidos, pero para hacer uso de la misma se requiere hacer referencia a la librería System.Configuration, los pasos para esta acción serian representados en la siguiente imagen:

Solo queda agregar el código que tomaría la información del archivo de configuración, usándolo luego con los objetos de ado.net para conectarse

En el punto 1 se define el “using” a la librería referenciada en el paso anterior (definiendo así su namespace), mientras que en el 2 se hace uso de la clase ConfigurationManager para tomar la cadena de conexión.

Por supuesto en el archivo de configuración se debió agregar la key que se define en el .config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="default" connectionString="Data Source=LecturaConnectionString\TestDb.sdf;Persist Security Info=False;"/>
  </connectionStrings>
</configuration>

2- Definir una sección key-value

Definir información del tipo key-value en el archivo de configuración puede realizarse de varias formas

  • usando la sección appsetting
  • por medio de una seccion custom creada por uno

 

2a- Usando AppSetting

Esta es la forma más simple y directa de definir valores simples en la configuración, solo basta con ingresar en la sección <appSettings> el tag “add” con cada item que se requiera.

En el ejemplo se observará la sección definida como:

<appSettings>
  <add key="1" value="Efectivo" />
  <add key="2" value="Tarjeta Credito" />
  <add key="3" value="Tarjeta Debito" />
  <add key="4" value="Cheque" />
  <add key="5" value="Transferencia Bancaria" />
</appSettings>

En el código, en el Form2, se trabaja con esta información con al ayuda de linq para cargar un combo

private void Form2_Load(object sender, EventArgs e)
{


    var result = (from configKey in ConfigurationManager.AppSettings.Keys.Cast<string>()
                  let configValue = ConfigurationManager.AppSettings[configKey]
                  select new
                  {
                      key = configKey,
                      value = configValue
                  }).ToList();

    
    cmbMediosPago.DisplayMember = "value";
    cmbMediosPago.ValueMember = "key";
    cmbMediosPago.DataSource = result;
    
}

Acceder a un ítem en concreto es tan simple como usar

ConfigurationManager.AppSettings[key]

 

private void cmbMediosPago_SelectionChangeCommitted(object sender, EventArgs e)
{
    string key = Convert.ToString(cmbMediosPago.SelectedValue);
    string value = ConfigurationManager.AppSettings[key];

    lblSeleccion.Text = string.Format("Se ha seleccionado\n Key:{0} \n Value:{1}", key, value);
}

2b- Definiendo una sección propia

El uso de la sección <appSettings> en algunas circunstancia puede resultar demasiado genérico y no brindar un lugar que sea claramente identificable para el negocio que se esta programando, esta sección al ser tan común se puede llenar rápidamente de items key-value no relacionados, haciendo difícil el mantenimiento.

Pero existe una alternativa a este problema y consiste en crear una sección propia para conserva estos pares key-value de forma personalizada, otorgando una visibilidad con sentido para la aplicación

En el código del Form3 se implementa la solución usando una sección definida por uno mismo, la cual aplica el mismo concepto key-value.

<configuration>
  <configSections>
    <section name="MediosPago" type="System.Configuration.DictionarySectionHandler" />
  </configSections>
  
  
  <MediosPago>
    <add key="1" value="Efectivo" />
    <add key="2" value="Tarjeta Credito" />
    <add key="3" value="Tarjeta Debito" />
    <add key="4" value="Cheque" />
    <add key="5" value="Transferencia Bancaria" />
  </MediosPago>
  
</configuration>

Para recuperar la información y listarla

private void Form3_Load(object sender, EventArgs e)
{

    var result = (from config in ((Hashtable)ConfigurationManager.GetSection("MediosPago")).Cast<DictionaryEntry>()
                 select new 
                 {
                     key = config.Key,
                     value = config.Value
                 }).ToList();

    cmbMediosPago.DisplayMember = "value";
    cmbMediosPago.ValueMember = "key";
    cmbMediosPago.DataSource = result;

    cmbMediosPago.SelectedIndex = -1;

}

Obtener un ítem basándonos en la key requiere recuperar la sección completa para luego si acceder al valor

private void cmbMediosPago_SelectionChangeCommitted(object sender, EventArgs e)
{
    string key = Convert.ToString(cmbMediosPago.SelectedValue);
    string value = ((Hashtable)ConfigurationManager.GetSection("MediosPago"))[key].ToString();

    lblSeleccion.Text = string.Format("Se ha seleccionado\n Key:{0} \n Value:{1}", key, value);
}

Por supuesto tanto en estos ejemplo hacer uso de las clase de configuración para tomar el valor del ítem seleccionado, no tiene un sentido practico, ya que el propio combobox proporciona ambos datos key y value (usando el SelectedValue y SelectedText), solo se realiza con fines ilustrativos para poder aplicar los conceptos de programación con el archivo de configuración.

 

Código de ejemplo

[C#]
[VB.NET]

11 comentarios:

Ulises dijo...

Hola Leandro, primero que nada agradecerte tu gran trabajo, he aprendido muchísimo gracias a tus artículos.

Ahora solo para molestarte si pudieras arreglar las ligas de las imágenes... Este tema me interesa mucho y como que si faltan las imágenes para saber de que estas hablando. Salu2

Leandro Tuttini dijo...

hola Ulises

espero lo mas pronto que pueda solucionar el problema que tengo con el hosting

mientras tanto si necesitas ver las las imagenes y archivos reemplaza el dominio ltuttini.com.ar por http://200.58.122.109/ltuttini.com.ar

por ejemplo, una de las imagenes dice:
http://www.ltuttini.com.ar/blogfiles/WinForms/ConfigSeccionesPropias/Parte1/imagen1.jpg

con el cambio quedaria:
http://200.58.122.109/ltuttini.com.ar/blogfiles/WinForms/ConfigSeccionesPropias/Parte1/imagen1.jpg


este problema es temporal, por eso no actualizo el articulo

saludos

Ulises dijo...

Mil gracias!! ahora si ya entendí todo :-D

Unknown dijo...

Saludos leandro,

es muy buena la utilidad de este proceso, pero al momento de ejecutar la aplicación y cambiar los valores de la configuración, no carga los valores actualizado, a que se debera?

Leandro Tuttini dijo...

hola Unknown

no se si entendi del todo

al cambiar los valores en que momento ? porque si es desde codigo recuerda que debes realizar un Refresh de la seccion de configuracion para que la tome

saludos

Josengan dijo...

Hola Leandro me intereso ese ejemplo. Pero tengo una duda si utilizo ya sea el appsetting o conexion string se puede modificar cuando la aplicacion se este ejecutando? He podido modificarlo pero me obliga a salir y volver a entrar al sistema para que se refleje el cambio. Saludos

Leandro Tuttini dijo...

hola Josengan

por lo general no se recomiendo cambiar informacion de configuracion mientras la aplciacion se ejecuta

pero si tienes un .exe ejecutandose y editas el .config al realziar la lectura con el ConfigurationManager deberia tomar el cambio

sino habria que evaluar de usar

ConfigurationManager.RefreshSection

saludos

GABRIEL VILLACIS dijo...

Hola Leandro, por favor ayudame:

Realizé un proyecto en 3 capas, siguiendo tambien tu tutorial e inclui un archivo app.config para los connectionstring, me funciona a la perfeccion..
Ahora necesito tener un instalador de la aplicacion, y surge el siguiente problema:

Estoy utilizando visual studio para hacer este instalador: arrastro el hasta el proyecto de instalacion archivo.exe(ejecutable) de mi proyecto y este como esta referenciado por defecto me carga las dll de las capas de datos y negocio... pero el archivo app.config no se agrega automaticamente, yo lo agrego como un archivo.... compilo el proyecto de instalacion, instalo mi aplicacion sobre el Sistema Operativo, al momento de ejecutar la aplicacion desde el SO como un programa independiente no se lee el app.config....
Estoy utilizando .Net Framework 4.

Insisto mientras estoy desarrollando, la utilizacion del .config va de maravilla, pero cuando llega la hora de instalar la aplicacion llega el problema...

Como resuelvo esto..???
Muchas gracias...
Espero tu pronta respuesta....

Leandro Tuttini dijo...

hola GABRIEL

el tema es que si lo arrastras como archivo este toma el nombre de App.config, cuando deberia tomar el NombreAplicacion.exe.config

o sea se renombra, esto lo puedes validar en el bin\Debug

lo raro es que en el instalador no incluya de forma automatico el config, hasta donde se deberia incluirlo dentro de la opcion de primary output

saludos

Valex dijo...

Hola Leandro, disculpa, tengo la necesidad de hacer exactamente lo mismo pero en asp.net con visual

estoy utilizando visual studio 2010 y esque quiero optimizar mi codigo porque cada webform tengo una cadena de conexión me podrias recomendar como configurarlo para tnerlo ubicado en un solo lado .. de ante mano muchas gracias

Leandro Tuttini dijo...

hola Valex

aplica de la misma forma, el ConfigurationManager lo puedes usar tambien en un entorno web

quizas la diferencia este en el uso del web.config en lugar del app.config

saludos