¿Cómo puedo agregar una restricción de tipo para incluir cualquier cosa serializable en un método genérico?

StackOverflow https://stackoverflow.com/questions/945495

Pregunta

Mi método genérico debe serializar el objeto que se le pasó, sin embargo, solo insistir en que implementa iserializable no parece funcionar. Por ejemplo, tengo una estructura devuelta de un servicio web (marcado con SerializableAttribute) que es seriala a XML muy bien, pero, como se esperaba, el compilador C# se queja.

¿Hay alguna forma de comprobar que el objeto es serializable antes de intentar serializarlo o, mejor aún, una forma de usar el where ¿La palabra clave para verificar el objeto es adecuado?

Aquí está 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?

¿Fue útil?

Solución

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

1) Pon el nuevo() restricción en el tipo genérico (para habilitar la capacidad de deserializar y garantizar que el XMLSerializer no se queje de la falta de CTOR predeterminado):

where T : new()

2) En la primera línea de su método que maneja la serialización (o constructor o en cualquier otro lugar que no tenga que repetirlo una y otra vez), puede realizar esta verificació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 cuando se trata de serializar un tipo, pero esto cubrirá los problemas más obvios.

Otros consejos

Escribí un artículo de blog de longitud sobre este tema que puede encontrar útil. Principalmente va a la serialización binaria, pero los conceptos son aplicables a la mayoría de cualquier formato de serialización.

Lo largo y corto es

  • No hay forma de agregar una restricción genérica confiable
  • La única forma de verificar y ver si un objeto estaba Serializable es serializarlo y ver si la operación tiene éxito

La única forma de saber si un objeto es serializable es tratar de serializarlo.

De hecho, estaba preguntando 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?

En vez de

XMLSerializer XMLSerializer = new XMLSerializer (typeof (t));

probar

XMLSerializer XMLSerializer = new XMLSerializer (Message.gettype ());

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top