Transmitiendo ExtendedProperties con Remoting


Uno de los valores que habitualmente se devuelven desde una llamada a un método remoto es el DataSet. Si es nuestro caso y además usamos la propiedad ExtendedProperties para almacenar otros datos que acompañan al DataSet nos daremos cuenta que sólo las propiedades introducidas como string se transmiten a través de la capa de remoting.
Una posible solución es cambiar el formato de serialización del dataset a binario cambiando la propiedad RemotingFormat, pero eso no siempre es posible ya que al usar un canal http y SOAP el DataSet volverá ignorará esa propiedad.
Para poder transmitir nuestros valores existe una solución rápida y que no afecta a cómo se programan las reglas de negocio: añadir una capa de serialización al canal de remoting.

Para ello necesitaremos un ServerChannelSink para serializar las propiedades y un ClientChannelSink para deserializarlas.

Creamos la clase:

public class ExtendedPropertiesServerSink :
BaseChannelObjectWithProperties, IServerChannelSink
{
IServerChannelSink _next;

public ExtendedPropertiesServerSink(IServerChannelSink next)
{
_next = next;
}

En la implementación del método ProcessMessage del interface tenemos el truco… Si la respuesta del método contiene un DataSet o DataTable entonces serializamos las extended properties.

public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
System.Runtime.Remoting.Messaging.IMessage requestMsg,
ITransportHeaders requestHeaders, System.IO.Stream requestStream,
out System.Runtime.Remoting.Messaging.IMessage responseMsg,
out ITransportHeaders responseHeaders,
out System.IO.Stream responseStream)
{
if (_next != null)
{
ServerProcessing spres = _next.ProcessMessage(sinkStack,
requestMsg, requestHeaders, requestStream, out responseMsg,
out responseHeaders, out responseStream);

ReturnMessage message = responseMsg as ReturnMessage;
if (message != null)
{
DataSet ds = message.ReturnValue as DataSet;
if (ds != null)
{
if (ds.RemotingFormat == SerializationFormat.Xml)
{
// serializa las propiedades extendidas del dataset
serializeExtendedProperties(ds.ExtendedProperties);
// para cada tabla también hace lo mismo
foreach (DataTable t in ds.Tables)
{
serializeExtendedProperties(t.ExtendedProperties);
}
}
}
else
{
DataTable t = message.ReturnValue as DataTable;
if (t != null)
{
if (t.RemotingFormat == SerializationFormat.Xml)
serializeExtendedProperties(t.ExtendedProperties);
}
}
}

return spres;
}
else
{
responseMsg = null;
responseHeaders = null;
responseStream = null;
return new ServerProcessing();
}
}

El método para serializar necesita que la clase sea serializable en xml (se puede controlar mediante atributos o implementando el interface IXmlSerializable):

private static void
serializeExtendedProperties(PropertyCollection propertyCollection)
{
foreach (object key in propertyCollection.Keys)
{
MiClase value = propertyCollection[key] as MiClase;
if (value != null)
{
XmlSerializer ser = new XmlSerializer(value.GetType());
using (StringWriter w = new StringWriter())
{
ser.Serialize(w, value);
propertyCollection[key] =
w.ToString();
}
}
}
}

Una vez serializadas las propiedades habrá que crear un deserializador en un ClientChannelSink y enlazarlos ambos con sendos ChannelSinkProvider para poderlos añadir a la configuración de remoting. En la parte servidor hay que colocar la entrada tras la del formatter SOAP:

<channel ref="http" port="5001"
displayName="http with props encoding">
<serverProviders>
<!-- support soap encoding -->
<formatter ref="soap" typeFilterLevel="Full" />
<!-- serialization layer -->
<provider type="RemotingTest.ExtendedPropsServerSinkProvider,
RemotingTest"/>
</serverProviders>
Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s