2009-06-03 21 views
31

Mi método genérico necesita serializar el objeto que se le pasa, sin embargo, simplemente insistir en que implementa ISerializable no parece funcionar. Por ejemplo, tengo una estructura devuelta desde un servicio web (marcado con SerializableAttribute) que se serializa a xml bien, pero, como se esperaba, el compilador de C# se queja.¿Cómo puedo agregar una restricción de tipo para incluir cualquier elemento serializable en un método genérico?

¿Hay alguna manera de verificar que el objeto sea serializable antes de intentar serializarlo o, mejor aún, utilizar la palabra clave where para verificar que el objeto sea adecuado?

Aquí es mi método completo:

public static void Push<T>(string url, T message) 
     where T : ISerializable 
{ 
    string xml = SerializeMessage(message); 

    // Send the message to Amazon SQS 
    SendMessageRequest sendReq = new SendMessageRequest { QueueUrl = url, MessageBody = xml }; 
    AmazonSQSClient client = new AmazonSQSClient(S3User, S3Pass); 
    client.SendMessage(sendReq); 
} 

Y SerializeMessage:

private static string SerializeMessage<T>(T message) 
{ 
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); 
    using (StringWriter stringWriter = new StringWriter()) 
    { 
     xmlSerializer.Serialize(stringWriter, message); 
     return stringWriter.ToString(); 
    } 
} 

Si esto no es posible, ¿cuál es la mejor manera de realizar una comprobación de que un objeto es serializable en tiempo de ejecución?

Respuesta

32

No se puede hacer esto totalmente a través de las limitaciones genéricas, pero se puede hacer un par de cosas para ayudar:

1) Coloque la nueva () restricción sobre el tipo genérico (para habilitar la capacidad de deserializar y para garantizar la XmlSerializer no se queja de la falta de Héctor por defecto):

where T : new() 

2) en la primera línea de su manejo de la serialización método (o constructor o cualquier otro lugar que no tiene que repetirlo una y otra vez), puede realizar esta comprobación:

if(!typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)))) 
    throw new InvalidOperationException("A serializable Type is required"); 

Por supuesto, todavía existe la posibilidad de excepciones de tiempo de ejecución al tratar de serializar un tipo, pero esto cubrirá los problemas más obvios.

+3

Esta respuesta es incorrecta, ya que dará falsos positivos. typeof (T) evalúa a System.Runtime.Type, que es ISerializable, por lo que siempre se evaluará como verdadero. Use esto en su lugar ... if (! Typeof (T) .IsSerializable &&! (Typeof (ISerializable) .IsAssignableFrom (typeof (T)))) –

+2

Gracias - se actualizó para la posteridad :) –

+1

Se ha eliminado la edición anterior de la publicación –

0

En lugar de

XmlSerializer XMLSerializer = new XmlSerializer (typeof (T));

tratar

XmlSerializer XMLSerializer = new XmlSerializer (message.GetType());

7

Escribí un artículo de blog extenso sobre este tema que puede ser útil. Se aplica principalmente a la serialización binaria, pero los conceptos son aplicables a la mayoría de los formatos de serialización.

El largo y corto de él es

  • No hay manera de agregar una restricción genérica fiable
  • La única manera de comprobar y ver si un objeto fue serializable es para serializarlo y ver si la operación tiene éxito
3

La única manera de saber si un objeto es serializable es intentar serializarlo.

De hecho, preguntaba cómo saber si un tipo "es serializable", pero la pregunta real será con respecto a los objetos. Algunas instancias de un tipo pueden no ser serializables, incluso si el tipo está marcado [Serializable]. Por ejemplo, ¿qué pasa si la instancia contiene referencias circulares?

Cuestiones relacionadas