Persistencia de Objetos con XPO

Julio 29, 2010 :: Posted by - Emilio Torrens :: Category - , , ,

Estos días estoy probando varias soluciones de persistencia de Objetos ya que estoy pensando seriamente dejar de usar Deklarit porque van muy lentos con las versiones.

El primero que he probado ha sido XPO de DevExpress, es bastante potente y fácil de usar aunque el generador de clases desde una BD existente es un poco pobre, no te genera las relaciones ni las tablas cuya PK este compuesta por varios campos, eso tendremos que solucionarlo a mano, aquí podéis ver como.

El tema de PK por múltiples campos se soluciona creando una estructura donde definimos la clave primaria y luego en la clase que mapeamos a la tabla definimos esa estructura como PK

public struct MyTablePK

{

    [Persistent("Field1")]

    public string FieldKey1;

    [Persistent("Field2")]

    public string FiledKey2;

}


[OptimisticLocking(false)]

[Persistent("Table")]

public class MyTable : XPBaseObject

{

    [Key(), Persistent()]

    public MyTablePK PK;

    public string Field3;

    public string Field4;

    public MyTable(Session session) : base(session) { }

    public MyTable() : base(Session.DefaultSession) { }

    public override void AfterConstruction() { base.AfterConstruction(); }

}

El tema de la relaciones se soluciona utilizando el atributo [Association] en la propiedad donde definimos la colección de objetos hijos indicándole el nombre que le hemos dado en el SQL al FK

[OptimisticLocking(false)]

[Persistent("Table")]

public class MyTable : XPBaseObject

{

    [Key(true)]

    public int PK;

    public string Field1;

    public string Field2;


    [Association("Table-ChildTable", typeof(MyChildTable)), Aggregated]

    public XPCollection Childs

    {

        get { return GetCollection("MyChildTable"); }

    }


    public MyTable(Session session) : base(session) { }

    public MyTable() : base(Session.DefaultSession) { }

    public override void AfterConstruction() { base.AfterConstruction(); }

}



[OptimisticLocking(false)]

[Persistent("ChilTable")]

public class MyChildTable : XPBaseObject

{

    public int FK;

    public int PK;

    public string Field1;

    public string Field2;

    public MyChildTable(Session session) : base(session) { }

    public MyChildTable() : base(Session.DefaultSession) { }

    public override void AfterConstruction() { base.AfterConstruction(); }

}

Pues nada, sigo probando cosas, ya iré comentando :)

Control Silverlight RichtTextBox

Julio 21, 2010 :: Posted by - Mario Andujar :: Category - , , ,

image

El otro día en el trabajo me pidieron si podía crear dos controles nuevos en Silverlight para poder introducir texto formateado y poder visionarlo.

Buscando por la red encontré una opción gratuita bastante buena para lo que me pedían. El control en si se encuentra en http://www.vectorlight.net/demos/richtextbox.aspx y es un editor de texto bastante completo (tiene incluso un diccionario ortográfico para corregir errores de escritura y agregar nuevas definiciones). Solo con cambiar y poner las cuatro opciones que me pedían ya quedaron realizados estos dos controles.

Trabajar con Listas (Skip, Take y OrderBy)

Junio 30, 2010 :: Posted by - Emilio Torrens :: Category - , ,
Un poco de código para trabajar con listas.
 
El otro día nos llegaba, en una lista de int, las edades de los paxes y querían que ordenáramos las de los niños de menor a mayor, de eso se puede sacar un ejemplo de uso de Take y Skip, G1 seria el numero de Adultos en la lista, G2 niños y G3 Bebes.
 
int G1 = 2;

int G2 = 3;

int G3 = 1;

List<int> Valores = new List<int>() { 35, 25, 9, 4, 5, 0 };

//Cogemos los valores del segundo Grupo, los ordenamos y los metemos en 

//una nueva lista

List<int> ValoresG2 = Valores.Skip(G1).Take(G2).OrderBy(c => c).ToList();

//Creamos la lista resultado con los valores del Grupo 1, los del Grupo 2 

//Ordenado y el Grupo 3

List<int> result = new List<int>();

result.AddRange(Valores.Take(G1));

result.AddRange(ValoresG2);

result.AddRange(Valores.Skip(G1 + G2));

Ya se que se puede hacer en menos líneas, pero es un ejemplo !!!!! :)

Objetos 2 byte[]

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

Estoy haciendo unas pruebas con un servicio de cache propio en el que guardamos los datos en byte[] en unos diccionarios, así que a quien pueda interesar, aquí os dejo los métodos de serializacion y desserializacion:

public static byte[] ToByteArray(Object obj)
{
    if (obj == null) return null;

    MemoryStream ms = new MemoryStream();
    BinaryFormatter b = new BinaryFormatter();
    b.Serialize(ms, obj);
    byte[] data = ms.ToArray();
    ms.Close();
    return data;
}

public static T ToObjectSerialize<T>(byte[] serializedObject)
{
    if (serializedObject == null) return default(T);

    MemoryStream ms = new MemoryStream();
    ms.Write(serializedObject, 0, serializedObject.Length);
    ms.Seek(0, 0);
    BinaryFormatter b = new BinaryFormatter();
    Object obj = b.Deserialize(ms);
    ms.Close();
    return (T)obj;
}

Cliente C# para Velocity

Abril 14, 2010 :: Posted by - Emilio Torrens :: Category - , , ,

Hoy he estado liado con este tema con unas pruebas básicas para probar el Cache del AppFabric

El Windows Server AppFabric Beta 2 lo he instalado en un Windows Server 2008 con el Framework 4.0 RC, ojo que tiene que ser el RC no puede ser el final, además tiene otros requisitos con el Windows Power Shell 2.0 RTM y algunas cosas mas, pero el instalador te avisa y te dice de donde bajarlos.

El cliente en C# con VS2010 y Framework 4.0, recién salido del horno :)

Creamos el proyecto cliente y le añadimos esta referencias del AppFabric (Encontraremos las dll en la carpeta C:\Windows\System32\AppFabric del servidor donde lo hayamos instalado

  • Microsoft.ApplicationServer.Caching.Client.dll
  • Microsoft.ApplicationServer.Caching.Core.dll
  • Microsoft.WindowsFabric.Common.dll
  • Microsoft.WindowsFabric.Data.Common.dll

Podemos configurar el cliente por código o en el AppConfig.

Por código:

private DataCache Client
 {
     get
     {
         if (dataCache != null) return dataCache;

         // Aqui los servidores de cache en este caso 1.
         DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];
         servers[0] = new DataCacheServerEndpoint("CACHESERVER", 22233);

         DataCacheFactoryConfiguration factoryConfig =
                                       new DataCacheFactoryConfiguration();
         factoryConfig.Servers = servers;

         DataCacheFactory mycacheFactory = new DataCacheFactory(factoryConfig);

         //El Cache, en este caso el que pone por defecto al instalarlo
         DataCache myDefaultCache = mycacheFactory.GetCache("default");

         dataCache = myDefaultCache;
         return dataCache;
     }
 }

Por configuración:

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!--configSections must be the FIRST element -->
  <configSections>
    <!-- required to read the <dataCacheClient> element -->
    <section name="dataCacheClient"
       type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
            Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
            Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       allowLocation="true"
       allowDefinition="Everywhere"/>
  </configSections>

  <dataCacheClient>
    <hosts>
      <host name="CACHESERVER" cachePort="22233"/>
    </hosts>
  </dataCacheClient>
</configuration>

Codigo:

private DataCache Client
      {
          get
          {
              if (dataCache != null) return dataCache;

              //Configurado en el app.config
              DataCacheFactory mycacheFactory = new DataCacheFactory();

              // Get a cache client for the cache "default".
              DataCache myDefaultCache = mycacheFactory.GetCache("default");

              dataCache = myDefaultCache;
              return dataCache;
          }
      }

Y listo para probarlo:

private void Test()
{
    DataCache cliente = Client;

    cliente.Add("key", "data");
    object data = cliente.Get("key");
    cliente.Remove("key");
}

Capturar evento click derecho con SilverLight

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

Aquí vemos como capturar el evento del botón derecho en silverlight.

Este evento desde la salida de silverlight ha estado inactivo, y dicen que en la siguiente versión, silverlight 4, estará disponible (también dijeron eso en la versión 3).

Cuando haces click derecho en la aplicación Silverlight te muestra un menú contextual y un dialogo de configuración.

¿Y si quieres usar el botón derecho en tu aplicación silverlight? El proceso es muy sencillo, y aquí os detallare unos pasos que deberéis de seguir para poder utilizar dicho evento y mostrar un menú contextual propio.

Paso 1: Tenemos que establecer el control de Silverlight para ventanas. En la pagina web del proyecto (suele ser default.aspx) que contiene el control Silverlight añadir la etiquetawindowless=”true”.

Paso 2: Introducimos el contextmenu donde queramos capturar el evento click derecho. Dentro del xaml creamos una nueva clase llamada ContextMenuInterceptor. En el constructor de esta clase capturamos un evento llamado “OnContextMenu” con HtmlPage.Document.AttachEvent (deberás agregar la referencia System.Window.Browser).

Dentro de este evento llamamos a e.PeventDefault(). Esto cancela la propagación del evento click derecho para que silverlight no lo reciba (así no mostrará su menu contextual).

En este punto, es cuando usted esta capturando el evento y podra mostrar o hacer cualquier cosa. En el ejemplo que pongo a continuación utilizo yo un TextBlock para mostrar cuando capturamos el click derecho.

Page.xml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace SilverlightApplication15
{
    public partial class Page : UserControl
    {
        ContextMenuInterceptor _cmi = null;
        public Page()
        {
            InitializeComponent();
            _cmi = new ContextMenuInterceptor(MyField);
        }
    }       

    public class ContextMenuInterceptor
    {
        TextBlock TextField;

        public ContextMenuInterceptor(TextBlock textField)
        {
            TextField = textField;
            HtmlPage.Document.AttachEvent("oncontextmenu", this.OnContextMenu);
        }

        private void OnContextMenu(object sender, HtmlEventArgs e)
        {
            TextField.Text = "Right Clicked Blocked at "+e.OffsetX+","+e.OffsetY;
            e.PreventDefault();
        }
    }
}

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 :)