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


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.

¿Hay alguna forma de verificar que el objeto sea serializable antes de intentar serializarlo o, mejor aún, una forma de utilizarlo? where palabra clave para verificar que el objeto sea 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 verificar que un objeto sea serializable en tiempo de ejecución?


32
2018-06-03 15:45


origen


Respuestas:


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

1) Poner el nuevo() restricción en el tipo genérico (para permitir la capacidad de deserializar y garantizar que 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 el constructor o en cualquier otro lugar, 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, aún existe la posibilidad de excepciones de tiempo de ejecución cuando se intenta serializar un tipo, pero esto cubrirá los problemas más obvios.


33
2018-06-03 15:50



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 eso 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

7
2018-06-03 15:47



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

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


3
2018-06-03 15:48



En lugar de

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

tratar

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


0
2018-06-03 15:47