Evolución de .Net Framework…

Con este post hago la introducción para poder empezar a hablar de algunos temas relacionados con el .Net Framework 3.5 y .Net Framework 3.5 SP1.

Para hacerlo más directo, veamos la siguiente imagen:

Las diferentes versiones del Fwk, con sus caracteristicas agregadas.

Las diferentes versiones del Fwk, con sus características agregadas.

En la imagen podemos ver las diferentes versiones del .Net Framework (empezando desde la 2.0) y las características que agregan a la programación.

Como ya sabemos, con el Fwk 2.0, con fecha de salida 07/11/2005, tenemos características como:

  • Common Language Runtime (CLR): entorno en tiempo de ejecución que ejecuta el código y proporciona servicios que facilitan el proceso de desarrollo.
  • WinForms: es una API incluida en el Fwk que se encarga de brindar aplicaciones clientes nativas de Windows.
  •  Web Services: el Fwk contiene un conjunto de clases para poder desarrollar Servicios Web seguros e interoperables basados en especificaciones abiertas. Un Web Service es un conjunto de protocolos y estándares que sirven para intercambiar datos entre aplicaciones utilizando redes (como Internet).
  • ASP.Net: es una tecnología libre que permite a los programadores crear aplicaciones Web dinámicas. El  Fwk 2.0 incorpora significativas mejoras en todas las áreas de ASP.NET, agrega controles nuevos, posibilidad de SKINs, Master Page, WebParts, manejo de perfiles, etc.
  • ADO.Net: se incorporaron mejoras en ADO.Net, sobretodo compatibilidad con UDT (tipos definidos por el usuario) y la posibilidad de tener varios MARS (conjuntos de resultados activos).
  • etc. (ver msdn)

Lo interesante viene de la mano del Fwk 3.0 y 3.5.

El Fwk 3.0, con fecha de salida 06/11/2006, incluye las siguientes agregados:

  • Windows Communication Foundation (WCF):  modelo de programación unificado para generar aplicaciones orientadas a servicios. Permite a los programadores generar soluciones con transacción seguras y de confianza, que se integren en diferentes plataformas y que interoperen con las inversiones existentes. Lo más importante de WCF es que permite unificar las distintas tecnologías de servicios, haciendo posible mantener el Servicio de Aplicación, más allá de la implementación «física» del mismo (configurable).
  • Windows Presentation Foundation (WPF): proporciona a los programadores un modelo de programación unificado con el que generar experiencias de cliente inteligentes de Windows, en las que se incorpora la interfaz de usuario, multimedia y documentos. WPF a diferencia de Windows Forms nos permite crear apliaciones más ricas en contenido y presentación para el usuario.
  • Windows Workflow Foundation (WF)es un componente del Fwk 3.0 que provee un modelo de programación para construir aplicaciones basadas en Workflows o Flujos de Trabajos. Un Workflow es una serie de actividades discretas involucrado en el proceso de negocio.
  • CardSpace: es la implementación de Microsoft de un metasistema de identidad que permite a los usuarios elegir una de una serie de identidades que les pertenecen, y utilizarla en contextos en que son aceptadas, independientemente de los sistemas de identidad subyacentes donde las identidades se originan y utilizan. O sea, es una implementación integrada que permite hacer que los usuarios se identifiquen en distintos sistemas, sin la necesidad de mantener un usuario y contraseña en cada uno de ellos.

Como último tomamos lo más nuevo, el Fwk 3.5, con fecha de salida 19/11/2007, incluye los siguientes agregados:

  • LINQ:  incorpora eficaces capacidades de consulta a la sintaxis de los lenguajes C# y Visual Basic en forma de patrones de consulta estándar fáciles de aprender. Esta tecnología se puede extender para que sea compatible con cualquier tipo de almacén de datos. .NET Framework 3.5 incluye ensamblados de proveedor de LINQ que habilitan el uso de LINQ para consultar colecciones de .NET Framework (LINQ to Objects), bases de datos de SQL Server (LINQ to SQL), conjuntos de datos ADO.NET (LINQ to DataSet) y documentos XML (LINQ to XML). Este es un tema muy interesante por explorar, asique lo estaré retomando en próximos posts.
  • AJAX: ASP.NET agrega compatibilidad con el desarrollo de AJAX centrado en el servidor mediante un conjunto de nuevos controles de servidor y nuevas API. Puede habilitar una página ASP.NET 2.0 existente en AJAX agregando un control ScriptManager y un control UpdatePanel, de modo que la página pueda actualizarse sin que sea necesario realizar una actualización de la página completa.
  • REST: integración de REST en WCF.
  • además modificaciones importantes en WCF, WPF y WF.
  • etc. (ver msdn)

Vale la pena destacar que actualmente se encuentra disponible el Fwk 3.5 SP1, con fecha de salida 11/08/2008, dicho Service Pack además de arreglar errores provee nuevas características:

  • ADO.NET Entity Framework: es una biblioteca de datos de alto nivel que aumenta el nivel de abstracción que los desarrolladores necesitamos para trabajar con los datos en las bases de datos relacionales. Brinda todas las clases y herramientas necesarias para poder trabajar en nuestras aplicaciones con objetos, a partir de un modelo de datos subyacente en Base de Datos relacionales. A diferencia de LINQ to SQL, ADO.Net EF no limita sus capacidades de Bases de Datos Sql Server. (ya lo retomaremos)
  • ADO.NET Data Services: servicio de publicación y federación de datos con una interface estándar usando REST. Expone un modelo de objetos (no una base de datos) sobre la web.
  • ASP.NET Dynamic Data: una característica que permite la creación rápida de aplicaciones web dirigidas por datos (aplicaciones con ABMs).  Permite la creación de aplicaciones web basándose en ASP.NET WebForms y ASP.NET MVC.
  • ASP.NET Routing: define puntos de entrada a la application. Genera URLs basado en una tabla de ruteo. Es aprovechado por ASP.NET.
  • se mejoró ASP.NET AJAX, WCF, WPF, WinForms.

Saludos!

Publicado en .NET 3.5. Etiquetas: . Leave a Comment »

Error: The command copy exited with code 1…

Problema:

Al compilar una librería de clases o ejecutable, aparece un error del tipo «The command copy … exited with code 1».

Solución:

Es un error que surge debido a que la librería o ejecutable ejecuta algún comando en los eventos Pre-Build o Post-Build (accesible desde las propiedades del proyecto actual), que en este caso es un copy… Deberíamos estar verificando la correcta sintaxis de los comandos que se ejecutan.

Configuración Pre-Build y Post-Build

Configuración Pre-Build y Post-Build

En mi caso me surgió este error debido a que una de las carpetas a la cual copiaba la dll no existía.

Publicado en Errores. Etiquetas: . 1 Comment »

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 »