Inicio Informática Programación .NET Serializar/Deserializar objetos .Net
 
Serializar/Deserializar objetos .Net E-mail
Escrito por Marcos   
Viernes, 09 de Diciembre de 2011 19:39

Este artículo es un complemento al artículo que ya publiqué en su día sobre serialización/deserializacion en .NET, lo que pasa es que con la experiencia se aprenden cositas que hasta que se aprenden dan algunos quebraderos de cabeza.

 

Todo surgió porque estaba realizando una aplicación cliente que mandaba un objeto serializado a otra aplicación servidor mediante un TCPClient y así se pueden compartir datos entre ellas.

 

Normalmente la aplicación cliente es un ensamblado y la aplicación servidor otro ensamblado. ¿Entonces cual es el problema? Que al serializar el objeto en el cliente, enviarlo y deserializarlo en el servidor aparece el siguiente mensaje:

BinaryFormatter.Deserialize is “Unable to find assembly”

 

¿Por qué? Porque al serializar un objeto, se guarda también la información del ensamblado. Entonces cuando el objeto llega al servidor (otro ensamblado) y se intenta deserializar, aunque tengamos una clase igual que la que existe en el cliente, el nombre del ensamblado es distinta, por eso, seguido del mensaje "Unable to find assembly" aparece el nombre del ensamblado del cliente.

 

¿Qué hacer? Fácil, solo hay que indicar al deserialiar, que la clase pertenece al ensamblado actual (en este caso, la parte servidor) para que así la encuentre.

 

¿Cómo?

Para ello en el BinaryFormatter hay que indicarle que justo antes de Deserializar el objeto, se llame a una clase que será la encargada de cambiar en el objeto el ensamblado al que pertenece.

 

Para esto se usa la propiedad Binder y se asigna a una nueva clase la cual implementa SerializationBinder.

 

Vamos con ejemplo para que quede más claro

 

Esta es la clase que queremos enviar a través de un socket.

 

namespace TestPassObjectBetweenApp
{
[Serializable]
class ClassToSend
{
private string _text = "";
   
public string Text
{
get { return _text; }
set { _text = value; }
}
}
}

 

Vemos que tiene el atributo [Serializable] para poder serializarla.

 

Esta es la clase que tenemos en el ensamblado de destino (donde vamos a enviar la clase a través de socket)

 

namespace Server
{
[Serializable]
class ClassToSend
{
private string _text = "";
 
public string Text
{
get { return _text; }
set { _text = value; }
}
 
}
}

 

 

Obviamente son iguales solo que pertenecen a ensamblados distintos.

 

Este es el código para enviar el objeto:

 

BinaryFormatter formatter = new BinaryFormatter();
TcpClient client = new TcpClient("localhost", 5555);
NetworkStream stream = client.GetStream();
ClassToSend obj = new ClassToSend();
formatter.Serialize(stream, obj);

 


Este es el código que lo recibe:

 

 

TcpListener listener = new TcpListener(5555);
listener.Start();
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
object obj = formatter.Deserialize(stream);

 

Bien, hasta aquí, si ejecutarmos esto, recibiríamos el siguiente código de error

Unable to find assembly 'TestPassObjectBetweenApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

 

Para solucionarlo entonces, como hemos dicho antes añadimos antes de deserializar el objeto, la linea

 

formatter.Binder = new Transform();

 

Y la clase Trasform es:

 

 

namespace Server
{
class Transform : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
typeName = typeName.Replace("TestPassObjectBetweenApp", "Server");
Type typeToDeserialize = Type.GetType(typeName);
 
return typeToDeserialize;
}
}
}

 

Si hacemos una traza, vemos como al deserializar, se llama a esta clase, se cambia el tipo de objeto y se devuelve este tipo.

 

Adjunto una solución hecha en VS2010 dónde lo he complicado un poco más y envio un List<ClassToSend> y dentro de ClassToSend tengo una propiedad que es otra clase.

TestPassObjectBetweenApp.zip

 

 

 

 

Última actualización el Domingo, 11 de Diciembre de 2011 17:17
 
 

Búsquedas

Idiomas

Spanish English French German Italian