Estamos desarrollando un servicio WCF para transmitir una gran cantidad de datos, por lo tanto, hemos elegido utilizar la funcionalidad WCF Streaming combinada con una serialización protobuf-net.Lazy, secuencia de objetos de transmisión de serialización con protobuf-net
Contexto:
general una idea es serializar objetos en el servicio, escribirlos en una corriente y enviar. En el otro extremo, la persona que llama recibirá un objeto Stream y podrá leer todos los datos.
Así Actualmente el código método de servicio se ve algo como esto:
public Result TestMethod(Parameter parameter)
{
// Create response
var responseObject = new BusinessResponse { Value = "some very large data"};
// The resposne have to be serialized in advance to intermediate MemoryStream
var stream = new MemoryStream();
serializer.Serialize(stream, responseObject);
stream.Position = 0;
// ResultBody is a stream, Result is a MessageContract
return new Result {ResultBody = stream};
}
El objeto BusinessResponse es serializado a un MemoryStream y que se volvió de un método. En el lado del cliente el código de llamada se ve así:
var parameter = new Parameter();
// Call the service method
var methodResult = channel.TestMethod(parameter);
// protobuf-net deserializer reads from a stream received from a service.
// while reading is performed by protobuf-net,
// on the service side WCF is actually reading from a
// memory stream where serialized message is stored
var result = serializer.Deserialize<BusinessResponse>(methodResult.ResultBody);
return result;
Así que cuando serializer.Deserialize()
se llama lo hace desde una corriente methodResult.ResultBody
, en el mismo tiempo en el WCF lado de servicio está leyendo un MemoryStream, que se ha vuelto de a TestMethod
.
Problema:
Lo que nos gustaría lograr es la de deshacerse de un MemoryStream
e inicial serialización de todo el objeto en el lado del servicio a la vez. Como utilizamos la transmisión, nos gustaría evitar tener un objeto serializado en la memoria antes de enviarlo.
Idea:
La solución perfecta sería devolver un objeto corriente a medida vacío (de TestMethod()
) con una referencia a un objeto que va a ser serializado (objeto 'BusinessResponse' en mi ejemplo) Entonces, cuando WCF llama a un método Read()
de mi transmisión, internamente serializo una parte de un objeto usando protobuf-net y lo devuelvo a la persona que llama sin almacenarlo en la memoria.
Y ahora hay un problema, porque lo que realmente necesitamos es una posibilidad de serializar un objeto pieza por pieza en el momento en que se lee la secuencia. Entiendo que esta es una forma de serialización totalmente diferente: en lugar de enviar un objeto a un serializador, me gustaría solicitar un contenido serializado pieza por pieza.
¿Es ese tipo de serialización de alguna manera posible usando protobuf-net?
¿Es este un objeto? O una serie de objetos (una colección)? Si vale la pena mirar esto en realidad depende de la configuración de WCF: en la mayoría de las configuraciones, siempre almacenará el mensaje completo en la memoria * de todos modos *, por lo que puede ser tan fácil no cambiar nada. –
Hola Marc, WCF está configurado para no utilizar el almacenamiento en búfer en absoluto, ese es el punto de la transmisión: quiero reducir la huella de memoria en el lado del servidor. Además, si quisiera serializar la colección de objetos, usaría 'SerializeWithLengthPrefix()' cada vez que el Cliente llama 'Read()' y mi buffer subyacente es más pequeño que el monto de datos solicitado. El problema aquí es que me gustaría poder dividir la serialización de un solo objeto. –
pregunta interesante. Pienso que * esto se puede generalizar, esencialmente a una secuencia de errores que hace que la lectura y la escritura funcionen como co-rutinas. Si no te importa tener un hilo adicional, se puede hacer con una simple puerta, sin embargo, iirc Jon tenía algunas ideas interesantes. Tendré que echarle un vistazo y contactarte. Sin embargo, puedo decir sin ninguna duda que no pretendo hackear el núcleo de protobuf-net para el propósito :) –