我的泛型方法需要序列化传递给它的对象,但只是坚持它实现ISerializable似乎不起作用。例如,我有一个从Web服务(标记为SerializableAttribute)返回的结构,它可以很好地序列化为xml,但正如预期的那样,C#编译器会抱怨。
有没有办法在尝试序列化之前检查对象是否可序列化,或者更好的是,使用where
关键字来检查对象是否合适?
这是我的完整方法:
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);
}
和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();
}
}
如果无法做到这一点,那么在运行时检查对象是否可序列化的最佳方法是什么?
答案 0 :(得分:37)
你不能完全通过通用约束来做到这一点,但你可以做一些事情来帮助:
1)将 new()约束放在泛型类型上(以启用反序列化功能并确保XmlSerializer不会抱怨缺少默认ctor):
where T : new()
2)在处理序列化的方法的第一行(或构造函数或其他任何你不必反复重复的方法),你可以执行此检查:
if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
throw new InvalidOperationException("A serializable Type is required");
当然,在尝试序列化类型时仍然存在运行时异常的可能性,但这将涵盖最明显的问题。
答案 1 :(得分:8)
我写了一篇关于这个主题的长篇博客文章,你可能会觉得有帮助。它主要用于二进制序列化,但这些概念适用于大多数序列化格式。
它的长短是
答案 2 :(得分:3)
了解对象是否可序列化的唯一方法是尝试序列化它。
事实上,你问的是如何判断类型是否“可序列化”,但实际的问题是关于对象。即使类型标记为[Serializable],某些类型的实例也可能无法序列化。例如,如果实例包含循环引用怎么办?
答案 3 :(得分:0)
而不是
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
尝试
XmlSerializer xmlSerializer = new XmlSerializer(message.GetType());