C# 如何添加类型约束以在泛型方法中包含任何可序列化的内容?

C# 如何添加类型约束以在泛型方法中包含任何可序列化的内容?,c#,generics,attributes,serializable,C#,Generics,Attributes,Serializable,我的泛型方法需要序列化传递给它的对象,但是仅仅坚持它实现ISerializable似乎不起作用。例如,我有一个从web服务(标记为SerializableAttribute)返回的结构,它可以很好地序列化为xml,但正如预期的那样,C#编译器会抱怨 是否有一种方法可以在尝试序列化对象之前检查对象是否可序列化,或者更好的方法是使用where关键字检查对象是否合适 以下是我的完整方法: public static void Push<T>(string url, T message)

我的泛型方法需要序列化传递给它的对象,但是仅仅坚持它实现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);
}
publicstaticvoidpush(字符串url,T消息)
其中T:ISerializable
{
字符串xml=序列化消息(消息);
//将消息发送到Amazon SQS
SendMessageRequest sendReq=new SendMessageRequest{QueueUrl=url,MessageBody=xml};
AmazonSQSClient=新的AmazonSQSClient(S3User,S3Pass);
client.SendMessage(sendReq);
}
和消息:

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();
    }
}
私有静态字符串序列化消息(T消息)
{
XmlSerializer XmlSerializer=新的XmlSerializer(typeof(T));
使用(StringWriter StringWriter=new StringWriter())
{
序列化(stringWriter,消息);
返回stringWriter.ToString();
}
}
如果这不可能,那么在运行时检查对象是否可序列化的最佳方法是什么?

而不是

XmlSerializer XmlSerializer=新的XmlSerializer(typeof(T))

试一试


XmlSerializer XmlSerializer=新的XmlSerializer(message.GetType())

我写了一篇关于这个主题的长篇博客文章,你可能会觉得很有帮助。它主要涉及二进制序列化,但这些概念适用于大多数任何序列化格式

长短不一是

  • 无法添加可靠的泛型约束
  • 检查和查看对象是否可序列化的唯一方法是将其序列化并查看操作是否成功

知道对象是否可序列化的唯一方法是尝试序列化它


事实上,您问的是如何判断类型是否“可序列化”,但实际的问题是关于对象的。某些类型的实例可能无法序列化,即使该类型标记为[serializable]。例如,如果实例包含循环引用怎么办?

您不能完全通过常规约束来实现这一点,但您可以做一些事情来帮助:

1) 将new()约束放在泛型类型上(以启用反序列化功能并确保XmlSerializer不会抱怨缺少默认构造函数):

2) 在处理序列化的方法的第一行(或构造函数或其他不必反复重复的地方),可以执行以下检查:

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

当然,尝试序列化类型时仍有可能出现运行时异常,但这将涵盖最明显的问题。

此答案不正确,因为它会给出误报。typeof(T)的计算结果为System.Runtime.Type,这是ISerializable,因此它将始终计算为true。用这个代替。。。如果(!typeof(T).IsSerializable&&!(typeof(ISerializable).IsAssignableFrom(typeof(T))),其中T:new()排除了带有可序列化属性的System.Tuple。True,但这看起来仍然相当安全。大多数人甚至不知道元组是什么,更不用说有一个.NET元组类了。另外,元组无论如何只会使用二进制序列化(没有XML)进行序列化,因为它没有默认的构造函数。
if( !typeof(T).IsSerializable && !(typeof(ISerializable).IsAssignableFrom(typeof(T)) ) )
    throw new InvalidOperationException("A serializable Type is required");