c# - ¿Cómo puedo agregar una restricción de tipo para incluir algo serializable en un método genérico?
generics attributes (4)
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 manera de verificar que el objeto sea serializable antes de intentar serializarlo o, mejor aún, una forma de utilizar la palabra clave where
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?
En lugar de
XmlSerializer xmlSerializer = new XmlSerializer (typeof (T));
tratar
XmlSerializer xmlSerializer = new XmlSerializer (message.GetType ());
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 comprobar y ver si un objeto era 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, 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?
No puede hacer esto totalmente a través de restricciones genéricas, pero puede hacer un par de cosas para ayudar:
1) Coloque la restricción new () en el tipo genérico (para habilitar la capacidad de deserializar y para 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.