Archivo de la etiqueta: .net

AppSettings de ficheros .config con tipado fuerte en c#

¡Hola!

No sé a vosotros, pero a mí me ha pasado más de una y de dos veces, eso de escribir mal una clave de configuración bien en el .config o bien en la llamada a ConfigurationManager.AppSettings[“…”], y volverme loco porque el código no funcionaba como yo quería.

Hace unos meses, un compañero me comentó que utilizaba una plantilla t4 (Text Template Transformation Toolkit)), para crear una clase estática a partir del contenido del a sección appSettings de un fichero web.config o App.config… Así que me puse a investigar un poco, y basándome en esta entrada del blog de “meie igapäevast IT’d anna meile igapäev”, me hice mi propio template para ese menester.

He de confesar que ahora no puedo vivir sin él 😉

Son unas pocas líneas de código. Solo tenéis que guardar el fichero en vuestro proyecto, añadir la referencia a System.Configuration si aún no la teníais, hacer click con el botón derecho sobre el fichero, pulsar en la opción “run custom tool”, y desde ese momento, podréis usar vuestra clase estática “AppSettings” con las claves de configuración que hayáis escrito en la sección “appSettings” de vuestro fichero config. El nombre de espacios generado será el mismo que el del ensamblado de vuestro proyecto, así que no tendréis que usar usings adicionales.

Varias consideraciones sobre la generación:

  • Las claves que contengan valores decimales se transformarán a propiedades de tipo decimal, siempre que la cultura del proyecto reconozca el formato de cadena como tal.
  • Las claves con contenido numérico entero se convertirán a propiedades de tipo entero.
  • Las claves cuyo contenido sea “true” o “false” se convertirán a propiedades booleanas.
  • En claves con caracteres no alfanuméricos, estos se reemplazarán por guiones bajos en su propiedad correspondiente.

Podéis descargar el fichero desde este enlace.

El código es el siguiente:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Configuration" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Configuration" #>
<#@ import namespace="System.Text.RegularExpressions"#>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO"#>
<#@ import namespace="System.Globalization" #>
using System.Configuration;
<# string ns = (string)System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint"); #>

namespace <#= ns#>
{
	public static class AppSettings {
<# 
	var configurationFileMap = new ExeConfigurationFileMap();
	string currentDir = Path.GetDirectoryName(this.Host.TemplateFile);
	string configFile = Path.Combine(currentDir, "Web.Config");
	if (!System.IO.File.Exists(configFile))
	{
		configFile = Path.Combine(currentDir, "App.Config");
	}
	if (!System.IO.File.Exists(configFile))
	{
		throw new System.IO.FileNotFoundException("No se encontró el fichero de configuración del que extraer los valores.");
	}

	configurationFileMap.ExeConfigFilename = configFile;
	var configuration = ConfigurationManager.OpenMappedExeConfiguration(configurationFileMap, ConfigurationUserLevel.None);
	foreach(KeyValueConfigurationElement setting in configuration.AppSettings.Settings)
	{ 
		if (setting.Key.Contains(":")) // estas suelen ser de ASP.NET MVC keys
		{
			continue;
		}
		// Reemplazamos todos los caracteres no alfanuméricos por guiones bajos
		string key = Regex.Replace(setting.Key, "[^a-zA-Z0-9]", "_");
		// Si la clave empieza por un número, le anteponemos el carácter 'N'
		if (Regex.IsMatch(key, "^[0-9]")) key = "N" + key;
		// Convertimos la clave a PascalCase. Normalmente me gusta poner las claves en
		// CamelCase, así que para que quede bien en .Net...
		key = key.Substring(0, 1).ToUpper() + key.Substring(1);
		string settingType;
		int i; bool b; decimal d;
		
		if (int.TryParse(setting.Value, out i))
		{
			settingType = "int";
		}
		else if (bool.TryParse(setting.Value, out b))
		{
			settingType = "bool";
		}
		else if (decimal.TryParse(setting.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out d))
		{
			settingType = "decimal";
		}
		else
		{
			#>
		public static string <#= key#> { get { return ConfigurationManager.AppSettings["<#= setting.Key #>"]; } }
<# continue;
} #>
		public static <#= settingType #> <#= key#> { get { return <#= settingType #>.Parse(ConfigurationManager.AppSettings["<#= setting.Key #>"]); }}
<#
} #>
	}
}

¡Espero que os sirva!

¡Un saludo!

Entrada visitada 99 veces

WCF. Usar excepciones nativas de .net en lugar de FaultException

¡Hola!

Para estrenar este blog, vengo con una entrada en la que os hablo de WCF, y de cómo propagar errores como Exception en lugar de usar FaultException.

¿Para qué puede servir esto?

Básicamente, en mi caso lo necesitaba para poder transmitir más información de la que por defecto FaultException transmite a la hora de lanzar un error.

Inconvenientes: Solo funcionará si tanto el servidor como el cliente están usando .net, pues esto por debajo usa Soap por interoperabilidad, pero al serializar exceptions, vamos a usar el NetDataContractSerializer; así que, ¡adiós a la interoperabilidad! 🙁

¿Ventajas? Si estamos trabajando con .net, podemos hacer cosas tan sencillas como:

try
{
    proxyCliente.RealizaOperacion();
}
catch (EntityException ex)
{
    // ...
}
catch (Exception exGeneral)
{
    // ...

Así, en nuestro error, podremos ver toda la información que el servidor posee sobre el mismo.

El artículo original es muy largo y está en inglés. Aquí os incluyo un adjunto como ejemplo para que veáis esto en código. Está compilado en Visual Studio 2010 (el original era de 2008), y queda bastante claro el ejemplo. De todas formas, aquí os dejo el artículo original en inglés.

¡Que os sirva! 🙂

WcfExtensions.zip

Entrada visitada 842 veces