miércoles, 17 de octubre de 2012

C# Avanzado - Extension method y Expresiones Lambda

Algo que estuve viendo hace poco y me pareció muy interesante son los Extension method que no es mucho mas que "extender" el comportamiento de una clase determinada sin modificar la misma. Cuales son las posibles utilidades de esto se preguntaran? bueno supongamos el hipotético caso de que tengan clases pertenecientes a una API de un cliente externo del cual no poseemos el código y necesitamos agregarle funcionalidad. Justamente para esto nos sirven los Extension method, para agregar métodos a una clase determinada sin necesidad de modificar la misma.

Supongamos ahora el caso que tenemos la siguiente clase


public class Equipo : IEnumerable<jugador>
{
 public IEnumerable<jugador> Jugadores { get; set; }

 IEnumerator IEnumerable.GetEnumerator()
 {
  return GetEnumerator();
 }

 public IEnumerator<jugador> GetEnumerator()
 {
  return Jugadores.GetEnumerator();
 }
}

public class Jugador
{
 public string Nombre { get; set; }
 public Posicion Posicion { get; set; }
}

public enum Posicion
{
 Arquero, Defensor, Mediocampista, Delantero
}

Entonces a nuestra clase Equipo lo que queremos agregarle es un método que aplique un filtro sobre la colección de Jugadores dependiendo del tipo de Posicion que tenga. Para esto lo que vamos a hacer es crear una clase ExtendedMethod la cual va a contener el método que va a realizar el filtrado de la colección.
Nuestra clase va a quedar asi


public static class ExtendedMethod
{
 public static IEnumerable<jugador> FiltrarPorPosicion(this IEnumerable<jugador> equip, Func<jugador, bool> param)
 {
  foreach (Jugador jugador in equip)
  {
   if (param(jugador))
    yield return jugador;
  }
 }
}

Vamos a explicar básicamente de que se trata el método FiltrarPorPosicion, como ya vieron recién este método recibe como parámetro del tipo IEnumerable donde aclaramos el tipo genérico a utilizar, este parámetro es simplemente la clase donde se va a agregar nuestro nuevo método. El segundo parámetro no es ni mas ni menos que nuestra expresión Lambda, la cual vamos a utilizar para realizar el filtrado, mas adelante vamos a hablar de como esta formada.
Mas abajo hay simplemente algo que a mi me parece una genialidad y es la palabra reservada yield, para que nos sirve, para generar una variable temporal del tipo de la colección que estamos a punto de devolver, nada mas ni nada menos, ¿una genialidad no?.

El llamado de este nuevo método lo podemos validar fácilmente de la siguiente manera, creando una nueva aplicación de consola.


class Program
{
 static void Main(string[] args)
 {
  IEnumerable<jugador> equip = new Equipo{
   Jugadores = new List <jugador>
       {
        new Jugador { Nombre = "Juan Carlos", Posicion = Posicion.Arquero },
        new Jugador { Nombre = "Jose Luis", Posicion = Posicion.Defensor },
        new Jugador { Nombre = "Pedro Ruben", Posicion = Posicion.Defensor },
        new Jugador { Nombre = "Juanito Perez", Posicion = Posicion.Mediocampista },
        new Jugador { Nombre = "Castulo Lopez", Posicion = Posicion.Delantero },
        new Jugador { Nombre = "Soberano Reimondo", Posicion = Posicion.Delantero },
       }
  };

  foreach(Jugador jug in equip.FiltrarPorPosicion(x => x.Posicion == Posicion.Delantero))
  {
   System.Console.WriteLine(jug.Nombre);
  }
  System.Console.Read();
 }
}

Como habrán podido ver esta herramienta es algo muy simple de implementar y a la vez muy potente. Antes de despedirme quiero dejarles un adelanto de lo que es Linq y como podríamos utilizarlo para hacer la selección de los equipos a filtrar, y seria algo así

public static class ExtendedMethod
{
 public static IEnumerable<jugador> FiltrarPorPosicion(this IEnumerable<jugador> equip, Func<jugador,bool> param)
 {
  return equip.Where(param);
 }
}

Bueno espero que como siempre lo hayan disfrutado y como saben cualquier duda o consulta el blog esta a su entera dispocición.

domingo, 14 de octubre de 2012

Aplicación distribuida - Servidor de chat! - Abstract + Primera parte

En estos dias dije que el primer paso para darle entidad a un proyecto era escribirlo, bueno evidentemente ayudo porque ya tengo la primer parte de lo que va a ser el desarrollo de esta aplicación distribuida, en este caso un servidor de chat distribuido.
La idea principal es generar una herramienta que mediante el uso de distintas funcionalidades de .net Framework como ser sockets, thread y I/O genere un chat donde todos los usuarios pueden ademas de "hablar" intercambiar archivos.
Para generarlo lo que vamos a hacer es ir generando las distintas funcionalidades por separado hasta llegar a la etapa de integración que nos va a dar como resultado la aplicación funcionando.

Para esta primer entrega el requerimiento va a ser el siguiente: Generar dos aplicaciones, una llamada Servidor y otra llamada Cliente que se conecten mediante el uso de sockets TCP/IP. El servidor tiene que estar preparado para aceptar múltiples conexiones (muchos clientes a la vez) y el procesamiento de la información que llega de cada cliente tiene que ser manejada mediante un thread independiente. El cliente al conectarse debe enviar un mensaje solicitando la conexión el cual el servidor contestara con un mensaje standar de bienvenida.

Veamos un poco la estructura de nuestra aplicación, en términos gráficos vamos a tener un proceso (aplicación servidor) que va a generar un socket de escucha en un puerto determinado (esto lo vamos a explicar mas adelante) y varias procesos clientes se van a conectar a ese socket, quedado algo así como lo que pueden ver en la imagen a continuación

Como crear un socket de escucha en C#

Vamos a ver a continuación que la creación de socket de escucha en C# es mucho mas practica (y simple) que para los que como yo están acostumbrados a hacer en C puede ser algo tosca.
Para esto, simplemente vamos a necesitar una instancia de la clase TcpListener.


var port = 10300;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
var serverSocket = new TcpListener(localAddr, port);
Para esto, como pueden ver en el código anterior solo necesitamos crear un objeto de esta clase con dos parámetros fundamentales: La ip y el puerto, requisitos básicos para hacer la conexión.
Con esto ya estamos listos para iniciar nuestro servidor y eso lo hacemos simplemente llamando a un método del objeto serverSocket, el Start que lo que va a realizar es crear un socket de escucha en el puerto indicado.

Como iniciar un nuevo thread

Ahora de acuerdo a nuestro primer requerimiento lo que necesitamos hacer es que nuestra aplicación se divida en n aplicaciones capaces de atender los pedidos que llegan de los clientes. Como ya dije varias veces el .net framework nos hace la vida mucho mas facil, y hacer esto que a simple vista parece muy complicado se reduce unicamente en crear un metodo estatico el cual va a ser invocado cada vez que nuestra aplicacion quiera "dividirse". Como vamos a hacer? solo debemos tener una instancia de la clase Thread


TcpClient client = serverSocket.AcceptTcpClient();
Thread t = new Thread(ThreadProc);
t.Start(client);

Y nuestro metodo ThreadProc va a estar definido asi


public static void ThreadProc(object info)
{
   ...Su codigo aqui
}
Con esto, cada vez que nuestra aplicación ejecute el método Start(); se creara un nuevo thread que va a atender los pedidos del cliente.

Si están interesados en ver el código completo del servidor y del cliente ambos están en el siguiente repositorio de GitHub https://github.com/skielo/DistributedChat.git . Desde ya están invitados a hacer un fork del repositorio para agregar su propia funcionalidad.


martes, 9 de octubre de 2012

Intentando volver, como escribir!

Bueno siempre hay tiempo para volver a empezar, las complicaciones del día a día me tienen un tanto apartado de la escritura, y como todos saben (al menos los que escriben en un blog) escribir entradas de calidad cuesta y mucho, hay que tomarse el tiempo para pensar que poner, y ponerlo en la forma adecuada, los ejemplos deben ser claros, y sobre todo, se debe disponer de tiempo para pensar un tema que sea verdaderamente importante para todos.
Sinceramente en este ultimo tiempo desde mi ultimo post tuve varios temas interesantes, como hablar de los proyectos que tengo en mente (para eso también se requiere tiempo, digo para esto de empezarlos LMAO), o continuar con las clases de C# básico (aunque esto me genera dudas saber si a alguien le son de utilidad.
De momento tengo varios proyectos en mente de los que estoy muy interesado, y creo que la mejor manera de darle comienzo es esta, escribirlos para darles entidad y que puedan tener vida, así que una breve enumeración de los mismos:

1.- Sistema de gestión de vehículos
2.- Una aplicación distribuida explicada paso a paso en C# (esta la tengo pensada para el blog, 100% educativo).
3.- Modulo de instalación para Catarse (https://github.com/skielo/catarse)
4.- Sistema de inteligencia artificial distribuido (Borg: http://es.wikipedia.org/wiki/Borg_(Star_Trek)

Como habrán visto el ultimo es el mas ostentoso, soberbio y grande proyecto que tengo en mente, para esto requiero de estar concentrado y sobre todo leer mucho sobre este tema, mi idea es ir documentando todo el material que voy leyendo en el blog para que la información procesada con mi entendimiento quede compartida.

Veremos como va funcionando, en principio voy a ir dedicando tiempo (un par de horas semanales) para mantener actualizado el blog.