Error: Unhandled exception en WinForms…

Como desarrolladores una de las cosas que debemos tener siempre en cuenta es la posibilidad de que una instrucción ocasionalmente produzca una excepción. Para capturar excepciones y manipularlas, lo hacemos con la ayuda de nuestros queridísimos try{}catch{}finally{}.

Sin embargo hay veces en que se nos pueden pasar de largo y terminar en lo que se denomina una excepción no manejada o unhandled exception. En esos casos, el resultado es un hermoso mensaje del framework como el que se muestra a continuación:

Mensaje de excepción no manejada de WinForm

Mensaje de excepción no manejada de WinForm

En casos como este, existe la posibilidad de reemplazar este mensaje por uno personalizado, quizás un poco mas amigable que el que nos brinda el framework.
Para personalizar el mensaje, podemos hacer uso del evento Application.ThreadException.

Ejemplo:

static class Program {

    [STAThread]
    static void Main() {
        //Manejamos excepciones no controladas
        Application.ThreadException += App_ThreadException;

        Application.Run(new Form1());
    }

    static void App_ThreadException(object sender, ThreadExceptionEventArgs e) {
        //El usuario desea continuar?
        StringBuilder msg = new StringBuilder();

        msg.AppendLine("Ooops! ha ocurrido un problema en la aplicación:");
        msg.AppendLine(e.Exception.Message);
        msg.Append("¿Desea continuar la ejecución de la aplicación?");

        DialogResult res = MessageBox.Show(msg.ToString(), "Error inesperado", 
            MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);

        if (res == DialogResult.Yes) {
            //Si desea continuar, no hacemos nada
            return;
        }
        else {
            //Si desea salir de la aplicación, la cerramos
            Application.Exit();
        }
    }
}

como resultado obtenemos el siguiente mensaje cuando ocurre una excepción no manejada:

Mensaje excepción no manejada personalizado

Mensaje excepción no manejada personalizado

Obviamente este no es más que un simple ejemplo. Además, cuando ocurre un error de este tipo, podriamos brindar más información o incluso permitirle al usuario enviar un mail que nos notifique que ocurrió un error, junto con la información del mismo, como ser StackTrace, Source, InnerException, etc. O simplemente no hacer nada….

Publicado en C#. Etiquetas: , . Leave a Comment »

REFLECTION: Invocar un método a partir de un String…

En esta segunda entrega les voy a mostrar como hacer para invocar un método, a partir de una cadena de String, la cual contiene simplemente el nombre del método.

Si inspeccionamos un poco la clase Type del framework podemos ver que tiene un método llamado Type.GetMethod(), el cual obtiene información de un método.
Lo que necesitamos saber de este método es que recibe como párametros el nombre del método y opcionalmente un Array con los tipos de los parámetros (para el caso de que exista sobrecargas de método), siendo que nos devuelve el MethodInfo relacionado.
Este MethodInfo tiene una gran cantidad de miembros, entre los cuales, los que se destacan son:

  • GetParameters(): obtiene los parámetros del método o constructor especificado.
  • GetType(): obtiene el objeto Type de la instancia actual.
  • Invoke(): realiza la llamada al método.
  • Attributes: obtiene los atributos asociados a este método.
  • IsConstructor.
  • IsAbstract, IsPrivate, IsPublic, IsStatic, IsVirtual.
  • ReturnType: obtiene el tipo de valor devuelto por este método.
  • Otros.

Lo que necesitamos utilizar entonces es el método Invoke(). La firma más común de este método es la Invoke(Object obj, Object[] parameters), donde:

  • obj: objeto en el que debe invocarse el miembro o constructor. Si el método o constructor es de clase o estático, se pasa null. Si, en cambio es un método o constructor de instancia, se debe pasar el objeto en el cual queremos ejecutar ese método.
  • parameters: lista de argumentos del método o constructor invocado. Este array debe tener el mismo número, orden y tipo que los parámetros del método o constructor que se va a invocar. Si no hay ningún parámetro, parameters debe ser null.

Les muestro un ejemplo, en el cual realizo una llamada a un método de clase o estático:

//obtengo el tipo
Type tipo = Type.GetType(namespaceTipo);

//obtengo la información del método, sé que no tiene sobrecargas
MethodInfo metodo = tipo.GetMethod(nombreMetodoEstatico);

DataSet ds = new DataSet();

//objeto que devuelve el método de clase
object objVuelta;

//tiene parámetros y sé que es un objeto de tipo DataSet 
objVuelta = metodo.Invoke(null, new object[] { ds }); 

otro ejemplo, pero con llamada a método de instancia:

//tengo una instancia
MiClase miInstancia = new MiClase();

//obtengo el tipo
Type tipo = miInstancia.GetType();

//Array de tipos
Type[] tiposParametros = new Type[] { typeof(Int32) };

//obtengo la información del método de instancia de la clase MiClase, sobrecarga de Int32
MethodInfo metodo = tipo.GetMethod(nombreMetodoInstancia, tiposParametros);

Int32 parametro = 3;

//invoco el método, con parámetro igual a 3
Object objVuelta = metodo.Invoke(miInstancia, new object[] { parametro }); 

REFLECTION: Crear una instancia a partir de un String con el nombre de la clase…

Hay muchas situaciones en las que se nos hace necesario crear una instancia de una clase a partir de una cadena de caracteres que tenemos almacenada, ya sea para utilizarla en una Factory o para mantener cierta abstracción en el tipo de datos que se maneja.
Cualquiera sea el caso, deberíamos tener un String con formato “assembly-qualified name”.
Comunmente se utiliza el siguiente formato:
“namespace+NombreClase, assembly”
(Es importante aclarar que la utilización de este String va a ser case-sensitive).

Ejemplos de assembly-qualified names:

  • “System.Int32”
  • “Configuracion.General.ClaseGeneral, Configuracion.General”
  • “TopNamespace.SubNameSpace.ClaseContenedora+ClaseAnidada, MiAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089”

Lo primero que debemos hacer es obtener el tipo a partir de la cadena de caracteres:

Type tipo = Type.GetType(namespaceControlador);

Una vez que tenemos el tipo, debemos obtener el constructor e invocarlo (en el siguiente ejemplo el constructor que se usa es el vacío):

IControlador controlador = (IControlador)tipo.GetConstructor(Type.EmptyTypes).Invoke(null);

Notar que es necesario tener una interface definida para ese tipo de datos o una clase abstracta de la cual herede, de lo contrario se nos haría casi imposible manejarlo (digo casi porque también podemos ejecutar un método a partir de un String).

GetConstructor(Type.EmptyTypes): obtiene el constructor a partir de los tipos de los parámetros que el mismo acepta. En este caso obtenemos el constructor que no tiene parámetros, en otros casos deberíamos pasarle un array con los tipos.
Invoke(null): invocamos el método (en este caso el constructor) pasandole los parámetros como un array, si le pasamos null es que ejecutamos el método sin parámetros.

¿Donde lo podemos utilizar?
En el proyecto en que trabajo necesitaba mantener cierta abstracción en cuanto a los controladores para los distintos tipos de tiqueteras fiscales y no fiscales. Entonces, lo que hice es crear una Factory la cual cuando se le especifica un tipo de tiquetera, va a un almacén de datos (Base de Datos o xml) en busca de un String con el nombre del controlador específico. Una vez teniendo ese String, creo el controlador usando reflection y lo uso… Así logro que el día de mañana si se agrega un nuevo tipo de tiquetera o un nuevo controlador, lo único que debo hacer es redefinir el String del controlador.

Enumeraciones + manipulación de bits = FLAGS…

Primero, lo primero… qué son las enumeraciones?
Una enumeración (enum) es una forma especial de tipo de valor, que deriva de System.Enum y proporciona nombres alternos para los valores de un tipo primitivo subyacente. Un tipo de enumeración tiene un nombre, un tipo subyacente y un conjunto de campos. (corrección)

Ejemplo:

public enum MessageBoxButtons {
    OK,
    OKCancel,
    AbortRetryIgnore,
    YesNoCancel,
    YesNo,
    RetryCancel
}

MessageBoxButtons boton = MessageBoxButtons.YesNo;

if (boton == MessageBoxButtons.YesNo) {
    //comportamiento propio de YesNo
}
else if (boton == MessageBoxButtons.YesNoCancel) {
    //comportamiento propio de YesNoCancel
}

En el ejemplo muestro la enumeración de MessageBoxButtons, que se utiliza en MessageBox, esta enumeración hace que cada cadena toma un valor (en este caso implícito) empezando por 0. Cada uno de los valores tiene un funcionamiento individual.

Si lo que necesitamos es permitir ingresar combinaciones de valores de la enumeración, lo que debemos usar es una enumeración del tipo Flags.
Las enumeraciones Flags se basan en la utilización de operaciones entre bits de sus valores. En las operaciones de manipulación de bits se utilizan muy frecuentemente los operadores & (AND), | (OR), ^ (XOR) y ~ (NOT). Si no saben como utilizar estos operadores, en este link pueden encontrar una guía en inglés muy interesante.
De antemano les puedo ir diciendo que las combinaciones se hacen (para estos casos) con el operador | y la evaluación de las condiciones con &.

La declaración de una enumeración Flags se hace de la siguiente manera:

[Flags]
public enum NombreEnumeracion {
    Cadena0 = 0, //opcional
    Cadena1 = 1,
    Cadena2 = 2,
    Cadena3 = 4,
    Cadena4 = 8,
    //...
}

Los valores que toman las cadenas son potencias enteras de 2, de ahí el tratamiento de bits.
Nada mejor que un ejemplo para comprender como utlizarlo:

[Flags]
public enum TipoLimpieza {
   Ninguna = 0,
   Cliente = 1,
   Servicio = 2,
   Todo = Cliente | Servicio
}

esta enumeración la utilicé en una tarea que tuve en la cual debía limpiar el caché de datos en el cliente, en el servidor, o en ambos…
Acá va la implementación:

TipoLimpieza tipo = (TipoLimpieza)objetoTipoLimpieza;

if (tipo == TipoLimpieza.Cliente) {
    //1. limpieza SOLO en cliente
}
if ((tipo & TipoLimpieza.Cliente) == TipoLimpieza.Cliente) {
   //2. limpieza en cliente, ya sea Cliente sólo o Cliente y Servicio
}
if ((tipo & TipoLimpieza.Servicio) == TipoLimpieza.Servicio) {
   //3. limpieza en servicio, ya sea servicio sólo o Servicio y Cliente
}
//notar que por la enumeración 0 (Ninguno) no se hace nada

entonces, al utilizarlo con los distintos valores:

//cuando:
tipo = TipoLimpieza.Ninguna;
//no se realiza nunguna operación.

//cuando:
tipo = TipoLimpieza.Cliente;
//se ejecuta el código de las condiciones: 1 y 2.

//cuando:
tipo = TipoLimpieza.Servicio;
//se ejecuta el código de la condición: 3.

//cuando:
tipo = TipoLimpieza.Cliente | TipoLimpieza.Servicio;
//se ejecuta el código de la condición: 2 y 3.
Publicado en C#. Etiquetas: . Leave a Comment »

Expresiones Regulares (Regex)…

Es común trabajar con expresiones regulares en los casos en que necesitamos saber si una cadena específica de caracteres cumple un patrón específico (lo que sería un expresión) y realizar alguna acción en base a ello.
Si no tienes conocimientos sobre expresiones regulares puedes comenzar aquí.

Un ejemplo en el que utilizaríamos expresiones regulares sería si necesitamos validar que una cadena ingresada por el usuario es un mail válido (cumpliendo con el formato común). También puede utilizarse para reemplazar partes de un texto que cumplen expresiones regulares.

En .Net, contamos con la clase Regex, la cual nos brinda varios métodos para manejar expresiones regulares.

[SerializableAttribute] 
public class Regex : ISerializable

Les muestro dos ejemplos de la utilización de Regex:
1. Validar los mails ingresados:

private const String PATRON_MAIL = @"^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$";

private void ValidarMails() {
    String[] mails = new String[3];
    mails[0] = "mimail@mail.com";
    mails[1] = "mimailmail.com";
    mails[2] = "mimail@mailcom";

    Regex reg = new Regex(PATRON_MAIL, RegexOptions.Singleline);

    foreach (String mail in mails) {
        if (reg.IsMatch(mail)) {
            Console.WriteLine("Mail: {0} es válido", mail);
        }
        else {
            Console.WriteLine("Mail: {0} es inválido", mail);
        }
    }
}

si es una llamada simple podemos utilizar el método estático:

Regex.IsMatch(textoAValidar, patron);

Resultado:
Mail: mimail@mail.com es válido
Mail: mimailmail.com es inválido
Mail: mimail@mailcom es inválido

2. Reemplazar una cadena a través de una expresión regular:

private const String PATRON_MAYOR = “[^>]>[^>]”;

private void ReemplazarTexto() {
String textoACambiar = “numero1>numero2>numero3”;

Regex rexMayores = new Regex(PATRON_MAYOR, RegexOptions.Singleline);

String textoNuevo = rexMayores.Replace(textoACambiar,
delegate(Match m) {
return String.Format(“{0}<{1}", m.Value[0], m.Value[2]); } ); Console.WriteLine("Antes {0} ahora {1}", textoACambiar, textoNuevo); } [/sourcecode] Resultado
Antes numero1>numero2>numero3 ahora numero1<numero2<numero3

En el ejemplo hicimos uso de un método anónimo el cual recibe como párametro un objeto Match, este método es el encargado de devolver el texto por el cual se reemplazará la cadena que coincide con la expresión regular. El método anónimo será ejecutado dos veces, una vez por cada fragmento de texto que cumpla con la expresión regular.

Ejemplos y más información sobre expresiones regulares: http://www.regular-expressions.info/.
Más ejemplos en .Net: http://msdn.microsoft.com/es-es/library/kweb790z(VS.80).aspx.
Una herramienta muy útil para crear y probar expresiones regulares es Rad Software Regular Expression Designer: http://www.radsoftware.com.au/regexdesigner/

Publicado en C#. Etiquetas: . Leave a Comment »

Como implementar correctamente IDisposable…

Primero lo primero… La interface IDisposable define un método “personalizado” para liberar los recursos administrados y no administrados.
IDisposable se usa principalmente para liberar los recursos no administrados, ya que el recolector de elementos no utilizados (GC: Garbage Collector) libera automáticamente la memoria asignada a un objeto administrado cuando ya no se utiliza, pero no se puede prever cuándo se producirá la recolección de elementos no utilizados. Además, el GC no reconoce recursos no administrados, como ser objetos de tipos File y Font.

A continuación, les muestro el código de ejemplo y aclaraciones sobre la implementación de una clase IDisposable:

public class ClaseDisposable : IDisposable {
    // Recursos manejados
    private Component componentes = new Component();
    private DataSet dataSetDisposable = new DataSet();

    // Indica si ya se llamo al método Dispose. (default = false)
    private Boolean disposed;

    /// <summary>
    /// Implementación de IDisposable. No se sobreescribe.
    /// </summary>
    public void Dispose() {
        this.Dispose(true);
        // GC.SupressFinalize quita de la cola de finalización al objeto.
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Limpia los recursos manejados y no manejados.
    /// </summary>
    /// <param name="disposing">
    /// Si es true, el método es llamado directamente o indirectamente
    /// desde el código del usuario.
    /// Si es false, el método es llamado por el finalizador
    /// y sólo los recursos no manejados son finalizados.
    /// </param>
    protected virtual void Dispose(bool disposing) {
        // Preguntamos si Dispose ya fue llamado.
        if (!this.disposed) {
            if (disposing) {
                // Llamamos al Dispose de todos los RECURSOS MANEJADOS.
                this.componentes.Dispose();
                this.dataSetDisposable.Dispose();
            }

            // Acá finalizamos correctamente los RECURSOS NO MANEJADOS
            // ...

        }
        this.disposed = true;
    }

    /// <summary>
    /// Destructor de la instancia
    /// </summary>
    ~ClaseDisposable() {
        this.Dispose(false);
    }
}

Podemos agregar que el método Dispose(bool disposing) es virtual, por lo que podemos redefinirlo en clases que hereden de esta, por lo cual en dichas clases no necesitamos implementar nuevamente IDisposable. Un ejemplo de este comportamiento es un Formulario que hereda (obviamente) de Form, como vemos a continuación, en Designer tenemos el siguiente código:

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
     if (disposing && (components != null)) {
          components.Dispose();
     }
     base.Dispose(disposing);
}

También podemos ver como sería la llamada a Dispose. Hay dos tipos de llamadas, la directa y la indirecta:
Llamada Directa:

ClaseDisposable objetoDisposable = new ClaseDisposable();
// utilizamos el objetoDisposable
// ...
// y lo finalizamos:
objetoDisposable.Dispose();

Llamada Indirecta:

using (ClaseDisposable objetoDisposable = new ClaseDisposable()) {
    // utilizamos el objetoDisposable
    // ...
}
//se finaliza automáticamente al salir del using

Más información sobre using…

Espero que les sea útil.
(FxCop nos sugiere la implementación de IDisposable de esta manera cuando nuestra clase trabaja con recursos administrados y que implementan el método Dispose… Es bueno hacerle caso, implementando IDisposable como corresponde 😀 )

Publicado en C#, Tips. Etiquetas: . Leave a Comment »

Operador as…

Les presento el operador as, es un operador de conversión bastante conocido, pero tiene características muy útiles que son interesantes de recalcar.

El operador as se utiliza para realizar conversiones entre tipos de referencia compatibles.

Veamos:

String cadena = objetoCadena as String;

sería (pero no lo es del todo) equivalente a:

String cadena = (String)algunObjeto;

Pero… ¿cuál es la verdadera diferencia?.
El operador as es similar a una operación de conversión de tipos; sin embargo, si la conversión no es posible, as devuelve null en lugar de producir una excepción.

Formalmente podemos decir que el operador realiza lo siguiente:

expresion is tipo ? (type)expresion : (type)null;

entonces lo utilizamos de la siguiente forma:

String cadena = objetoCadena as String;
if (cadena != null) {
    //objetoCadena ES un String.
}
else {
    //objetoCadena NO ES un String.
}

que es equivalente (y más performante) a:

if (objetoCadena is String) {
    //objetoCadena ES un string.
    String cadena = (String)objetoCadena;
}

NOTA: digo que as es más performante que el último ejemplo porque al realizar “objetoCadena is String” se realiza un casteo interno, siendo que después nosotros nuevamente lo realizamos dentro del if.
(FxCop notifica con un issue que realicemos este cambio de implementación)

Publicado en C#, Tips. Etiquetas: . 2 Comments »