Dependency Injection con Microsoft.Practices.Unity

Marzo 11, 2010 :: Posted by - Emilio Torrens :: Category - , ,

Microsoft.Practices.Unity  nos permite mapear una Clase a un Interface a través de una configuración en el .config de la aplicación, de esta manera podemos cambiar el comportamiento o el escenario en el que esta se ejecuta la aplicación tocando solo esa configuración.

Aquí dejo un ejemplo básico:

1-Creamos el Interface

public interface IMessage
{
    string Get();
}

2-Creamos las clases que implementan el interface

public class Message1 : IMessage
{
    public string Get()
    {
        return "Desde Message 1";
    }
}

public class Message2 : IMessage
{
    public string Get()
    {
        return "Desde Message 2";
    }
}

3-Creamos la clase donde usaremos el Interface, en esta debemos definir un campo del tipo del interface marcado como [Dependency] y un método de load para cargar la clase que corresponde en el interface

public class Message
{
    [Dependency]
    public IMessage IMessage { get; set; }

    public static Message Instance
    {
        get
        {
            using (IUnityContainer container = new UnityContainer())
            {
                UnityConfigurationSection ConfigurationSection =
                    (UnityConfigurationSection)
                    ConfigurationManager.GetSection("DITest");
                ConfigurationSection.Containers.Default.Configure(container);
                Message objMessage = container.Resolve<Message>();
                return objMessage;
            }
        }
    }
}

4-Creamos el archivo de configuración donde hacemos el mapeo

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
  <section name="DITest"
           type="Microsoft.Practices.Unity.Configuration.
                       UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <DITest>
    <containers>
      <container>
        <types>
          <type type="DITest.IMessage,DITest"
                mapTo="DITest.Message2,DITest"/>
        </types>
      </container>
    </containers>
  </DITest>
</configuration>

5-Probamos el código desde la consola y vamos cambiando el “mapTo†del archivo de configuración para ir viendo el cambio

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Message.Instance.IMessage.Get());
        Console.ReadLine();
    }
}

SoapHeader, SoapExtensions y Herencia

Diciembre 03, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Hace unos días Jordi escribió sobre las SoapExtensions y yo sobre las SoapHeaders, hoy le añadimos herencia y vemos como ahorrarnos bastante código y trabajo en una capa de servicios. :)

La idea es que todos los métodos de todos los servicios web de la aplicación se autentifiquen en el mismo sitio y no tener que poner el código de autentificación en cada método, además no queremos usar cookies ni mantenimiento de sesión.

Para esto usaremos una Cabecera Soap donde el cliente nos enviara Usuario y Contraseña, debemos crear la clase cabecera:

public class SoapHeaderCredentials : SoapHeader
{
    public string Password = "";
    public string UserName = "";
}

Cada servicio web tiene que tener una propiedad con la Cabecera, para ahorrarnos el escribirlo cada vez, creamos una clase que herede de WebService, que contenga la propiedad y heredamos los servicios web de esa clase:

public class MyWebService : System.Web.Services.WebService
{
    public SoapHeaderCredentials soapHeaderCredentials;
}

public class Service : MyWebService

Después creamos una Extensión Soap de autentificación (en este caso la llamamos AuthenticationExtension), Jordi ya explica aquí como crearlas así que solo pongo el código que nos interesa, que es donde buscamos la Cabecera Soap en el Método ProcessMessage:

case SoapMessageStage.AfterDeserialize:
{
    var o = from h in message.Headers.Cast<SoapHeader>()
            where h.GetType() == typeof(SoapHeaderCredentials)
            select h ;
    SoapHeaderCredentials soapHeaderCredentials =
        (SoapHeaderCredentials) o.First();
    AuthenticateUser(
        new Credentials()
        {
          UserName = soapHeaderCredentials.UserName,
          Password = soapHeaderCredentials.Password,
        }, 
      );
    break;
}

Después solo queda añadir los dos atributos [SoapHeader("soapHeaderCredentials")]  y [AuthenticationExtension()] a nuestros WebMethods, eso hará que los métodos tengan la cabecera de usuario y contraseña y que ejecuten el código de autentificación al recibir un mensaje:

[WebMethod]
[SoapHeader("soapHeaderCredentials")]
[AuthenticationExtension()]
public string HelloWorld()
{
    return "Hello World";
}

Y listo :)

Serializar y Deserializar nuestras clases

Noviembre 30, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Es sencillo obtener una representación XML de nuestras clases con el método ToString, solo hemos de sobrescribirlo por este:

public override string ToString()
{
    XmlSerializer ser = new XmlSerializer(this.GetType());
    StringWriter sw = new StringWriter();

    ser.Serialize(sw, this);

    sw.Flush();
    sw.Close();
    return sw.ToString();
}

También podemos crearlas desde su representación XML:

public static MyClass CreateFromXml(string xml)
{
    XmlSerializer ser = new XmlSerializer(typeof(MyClass));
    StringWriter sw = new StringWriter();

    return (MyClass) ser.Deserialize(new StringReader(xml));
}

Todo el Código de ejemplo:

public class MyClass
{
    public string Data1 { get; set; }
    public string Data2 { get; set; }

    public static MyClass CreateFromXml(string xml)
    {
        XmlSerializer ser = new XmlSerializer(typeof(MyClass));
        StringWriter sw = new StringWriter();

        return (MyClass) ser.Deserialize(new StringReader(xml));
    }

    public override string ToString()
    {
        XmlSerializer ser = new XmlSerializer(this.GetType());
        StringWriter sw = new StringWriter();

        ser.Serialize(sw, this);

        sw.Flush();
        sw.Close();
        return sw.ToString();
    }

    public void Test()
    {
        MyClass c = new MyClass();
        c.Data1 = "Hola";
        c.Data2 = "Como Estas";

        string xMyClass = c.ToString();

        MyClass copy = MyClass.CreateFromXml(xMyClass);
    }
}

Nos puede ser muy útil para temas de log, guardar los datos en las desconexiones, para debugear o para transportar la clases en XML entre aplicaciones.

MonoTouch o C# para IPhone

Septiembre 30, 2009 :: Posted by - Emilio Torrens :: Category - , ,

MonoTouchMonoTouch permite a los programadores .NET desarrollar aplicaciones en C# y ejecutarlas en el IPhone o el IPod Touch.

Necesitas un MAC para programarlo, además del SDK de IPhone, si encima quieres probar tu código en un IPhone o tener la posibilidad de distribuir tus aplicaciones tienes que formar parte del “Apple’s IPhone Developers Programâ€

Es de pago y se presenta en 3 versiones, Profesional,  Enterprise y Enterprise 5, aquí puedes ver las diferencias en las versiones, aunque tienes una versión Trial si te interesa pegarle un vistazo ;)

 

Como principales características:

  • C# y .NET en el iPhone
  • .NET Bindings al API Nativo
  • Posibilidad de Distribucion en el Apple App Store
  • Integración con MonoDevelop
  • Integración con XCode

Yo no creo que me lie con esto a no ser que algún cliente me “obligue†pero Jordi seguro que si, así que ya pondrá algo :)

Comunicar Servicios Win32 con WCF

Septiembre 25, 2009 :: Posted by - Emilio Torrens :: Category - , ,

WCFEstamos haciendo unos cambios en una de nuestras aplicaciones para que funcione relativamente bien en entornos de alta disponibilidad, uno de los cambios es que los Servicios Win32, que no pueden estar activos a la vez en varios servidores, se comuniquen entre ellos de manera que siempre uno, pero solo uno de la “granja†este activo.

Para eso hemos usado comunicación TCP con WCF, cada Servicio Win32 es servidor y cliente a la vez, de esa manera se comunican en forma de árbol para saber si tienen que activarse o no.

En este Post no me enrollare con todo el sistema solo sobre como hostear un servicio WCF en un Servicio Win32 y como crear un cliente para consumirlo.

Podemos añadir el servicio al proyecto con el témplate o añadirlo a mano, en realidad solo se trata de una clase, un interface y una nueva sección en el app.config

En el interface definimos el servicio y los métodos:

namespace Service
{
    [ServiceContract]
    public interface IMyTcpServer
    {
        [OperationContract]
        bool Ping();
    }
} 

La clase debe implementar el interface y es donde pondremos el código:

namespace Service
{
    public class MyTcpServer : IMyTcpServer
    {

        public bool Ping()
        {
            return true;
        }

    }
}

La sección del app.config donde definiremos que tipo de comunicación queremos, la dirección, el puerto, etc., en este caso comunicación tcp en el puerto 8731

<services>
  <service behaviorConfiguration="Service.MyTcpServerBehavior"
    name="Service.MyTcpServer">
    <endpoint address="" binding="netTcpBinding"
              contract="Service.IMyTcpServer">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding"
              contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Service/MyTcpServer/" />
      </baseAddresses>
    </host>
  </service>
</services>

Ya tenemos el servicio configurado, solo nos queda poner código en el OnStart del servicio Win32 para arrancarlo, el código es el siguiente:

ServiceHost tcpHostServer = new ServiceHost(typeof(MyTcpServer));
tcpHostServer.Open();

Ya tenemos nuestro servicio Win32 con su método de ping para poder comprobar si esta funcionando o no.

La parte cliente es realmente sencilla, ya que añadimos una Referencia de Servicio, como hacíamos antes con una referencia web, y el IDE nos crea todo el código necesario para consumir el servicio, la única diferencia es que el cliente no tiene una propiedad para indicarle la dirección del servicio, para indicarle una dirección distinta a la que crea en app.config cuando añadimos la referencia hay que hacerlo de la siguiente manera:

NetTcpBinding netTcpBinding = new NetTcpBinding();
EndpointAddress endpointAddress =
    new EndpointAddress("net.tcp://direccion:elPuerto/ElServicio/");
using (MyTcpServerClient client =
       new MyTcpServerClient(netTcpBinding, endpointAddress))
{
    return client.Ping();
}

Y listo :)
            

Interfaces y Diferentes contextos de Datos

Julio 14, 2009 :: Posted by - Emilio Torrens :: Category - ,

El otro día en el trabajo se nos presento un problema, teníamos una librería que se encargaba de convertir un XML de un cliente a un formato interno nuestro, esta librería era compartida por varias de nuestras aplicaciones, resulta que el cliente hace un cambio de especificaciones por lo que necesitamos acceder a unos datos históricos a fin de poder seguir convirtiendo su XML a nuestro formato, pero el modo y de donde obtener esos datos cambia según en el contexto en el que se este ejecutando la DLL.

La solución, añadirle un parámetro al método de conversión, un Interface que sea el que encargado de obtener esos datos, luego en cada contexto le pasamos la clase que nos interese que tiene que implementar el Interface.

Un Ejemplo en PseudoCodigo :)

//El interface que usaremos para obtener los datos
public interface IObtenerLosDatos
{
    XmlDocument DameLosDatos();
}

//El metodo que convierte el XML
public XmlDocument ConvierteXml(XmlDocument xmlDoc,
                                IObtenerLosDatos BuscardorDatos)
{
    XmlDocument xDatosHistoricos =
        BuscardorDatos.DameLosDatos();
    //Codigos
    //Codigos
    //Codidos
    return new XmlDocument();
}

//Una clase para obtener el historico desde el disco
public class DatosDesdeDisco: IObtenerLosDatos
{
    public XmlDocument DameLosDatos()
    {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(@"C:\Historico.xml");
        return xmlDocument();
    }
}

//Una clase para obtener el historico desde la base de datos
public class DatosDesdeSQL: IObtenerLosDatos
{
    public XmlDocument DameLosDatos()
    {
        XmlDocument xmlDocument =
            SqlHelper.Instance.GetXmlDocument();
        return xmlDocument;
    }
}

//Convertimos el XML
static void Convierte(XmlDocument xmlCliente)
{
    Program p = new Program();

    //Convertimos el XMl con el Historico desde Disco
    DatosDesdeDisco datosDesdeDisco = new DatosDesdeDisco();
    XmlDocument xmlConvertido1 =
        p.ConvierteXml(xmlCliente, datosDesdeDisco);

    //Convertimos el XMl con el Historico desde SQL
    DatosDesdeSQL datosDesdeSQL = new DatosDesdeSQL();
    XmlDocument xmlConvertido2 =
        p.ConvierteXml(xmlCliente, datosDesdeSQL);
}

Performance en LINQ 2 Objects

Junio 25, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Estaba comprobando el performance de una aplicación con ANTS Profiler y me he dado cuenta que tienes que ir con mucho ojito cuando trabajas con los resultados de una sentencia LINQ, en el código que os pego reglaCol es el resultado de una sentencia LINQ a Objetos:

Podéis ver que se ejecuta dos veces, una vez cuando la uso en el foreach:

image

y otra cuando la copia a una Lista:

image

Hasta ahora yo creía que la segunda vez que accedías no se ejecutaba si no que tenia la información en algún cache, pero se ve que no, así que copiándola a la lista antes del foreach y usando la lista en el foreach hay una mejora importante de rendimiento sin hacer prácticamente nada.

Si esto no es así que alguien me corrija pls, porque me he quedado a cuadros …

Eliminar repetidos con IEqualityComparer

Junio 19, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Estaba escribiendo un POST sobre usar IEqualityComparer para eliminar los objetos repetidos de una colección sin demasiado código, pero no funciona !!!

Hemos estado probándolo en un código aquí en el trabajo y eso no va, o no hace lo que esperabamos :(

Al final la manera que hemos usando es usando un ExtensionMethod y una Método de comparación, siguiendo lo que hemos leído en este blog:
http://blog.jordanterrell.com/post/LINQ-Distinct()-does-not-work-as-expected.aspx

La idea es crear la extensión en una clase estática:

namespace MyNameSpace
{
    public static class  ExtensionMethods
    {
        public static IEnumerable<T> RemoveDuplicates<T>
             (this IEnumerable<T> source, Func<T, T, bool> equater)
        {
            List<T> result = new List<T>();

            foreach (T item in source)
            {
                if (result.All(t => !equater(item, t)))
                {
                    result.Add(item);
                }
            }

            return result;
        }

    }
}

Esto hará que este método se añada a las colecciones de clases que estén en el mismo espacio de nombres, luego solo hay que crear el método que usaremos para comparar las clases, en mi caso uno que mira si los campos son iguales:

public static bool MyClassEquals(MyClass rec1, MyClass rec2)
{
    Type t = rec1.GetType();
    FieldInfo[] fi = t.GetFields();

    for (int i = 0; i < fi.Length; i++)
    {
        if (fi[i].GetValue(rec1).ToString() !=
            fi[i].GetValue(rec2).ToString())
            return false;
    }

    return true;
}

Y ya estamos listos para usarlo :)

foreach (MyClass c in MyClassList.RemoveDuplicates(MyClassEquals))

Aplicaciones Facebook

Junio 12, 2009 :: Posted by - Emilio Torrens :: Category - , ,

doyouhaceafacebookAyer empecé a investigar y a documentarme un poco para programar una aplicación para Facebook, la idea final es montar un sistema de geolocalizacion, una parte servidora y una parte cliente que correría en IPhone, Windows Mobile y Android , y permitiera geolocalizar en Facebook al usuario cuando hace el update del status usando el GPS del móvil.

Se que es ambicioso como primer proyecto así que tengo pensado hacer algunas aplicaciones mas sencillas antes para ver como va el tema.

Aun tengo que ver si consigo liar a Jordi y alguno mas para que me ayuden ya que es un proyecto free que tendría que hacer en mi tiempo libre y bueno tampoco tengo tanto tiempo libre.

Con eso de que el proyecto me lo tengo que financiar yo mismo tengo que tomar la decisión de donde alojarlo, porque las aplicaciones de facebook las tienes que alojar tu según he leído, dependiendo de eso usare el api php que te proporciona Facebook o Facebook.NET que es un API para programar con el .NET Framework.

Si usamos Facebook.NET será mas fácil pero esta el tema de los costes, luego necesitare alojarlo en Windows Server + IIS (y en los servidores de la oficina ya no me dejan alojar mas cositas personales :) ), si uso el api php de facebook lo puedo alojar aquí mismo, pero nos llevara mas trabajo ya que no es nuestra especialidad, así que no se que hacer, sugerencias? …

Aquí dejo algunas referencias por si os interesa meteros en este tema:

Bueno ya iré posteando como avanza el proyecto y si a alguno le interesa apuntarse mailme :)

LINQ to SQL, orderby y Take

Mayo 12, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Con LINQ 2 SQL y usando Take, es realmente sencillo obtener los últimos o los primeros registros de una Tabla, simplemente tenemos que ordenarla como nos interese con el order by y usar el método Take para indicar cuantos registros queremos.

Aquí dejo un ejemplo para coger los últimos registros de una tabla.

   public List<object> GetLastRecords(int NoOfRecords)
        {
            var records =
                (from r in DataClassesDataContext.Table
                 orderby r.Pk descending select r).Take(NoOfRecords);

            List<object> Result = new List<object>();

            foreach (Record record in records)
            {
                Result.Add(records);
            }

            return Result;
        }