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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/945495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:57:12  来源:igfitidea点击:

How can I add a type constraint to include anything serializable in a generic method?

c#genericsattributesserializable

提问by Matt Brindley

My generic method needs to serialize the object passed to it, however just insisting that it implements ISerializable doesn't seem to work. For example, I have a struct returned from a web service (marked with SerializableAttribute) that serializes to xml just fine, but, as expected, the C# compiler complains.

我的通用方法需要序列化传递给它的对象,但是仅仅坚持它实现 ISerializable 似乎不起作用。例如,我有一个从 web 服务返回的结构(用 SerializableAttribute 标记),它可以很好地序列化为 xml,但是,正如预期的那样,C# 编译器会抱怨。

Is there a way I can check the object is serializable before attempting to serialize it, or, better still, a way of using the wherekeyword to check the object is suitable?

有没有一种方法可以在尝试序列化之前检查对象是否可序列化,或者更好的是,使用where关键字来检查对象的方法是否合适?

Here's my full method:

这是我的完整方法:

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);
}

And SerializeMessage:

和 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();
    }
}

If this isn't possible, what's the best way to perform a check that an object is serializable at runtime?

如果这是不可能的,那么在运行时检查对象是否可序列化的最佳方法是什么?

采纳答案by Adam Sills

You can't do this totally via generic constraints, but you can do a couple things to help:

你不能完全通过通用约束来做到这一点,但你可以做一些事情来帮助:

1) Put the new()constraint on the generic type (to enable the ability to deserialize and to ensure the XmlSerializer doesn't complain about a lack of default ctor):

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

where T : new()

2) On the first line of your method handling the serialization (or constructor or anywhere else you don't have to repeat it over and over), you can perform this check:

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

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

Of course, there's still the possibility of runtime exceptions when trying to serialize a type, but this will cover the most obvious issues.

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

回答by Peter

Instead of

代替

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

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

try

尝试

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

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

回答by JaredPar

I wrote a length blog article on this subject that you may find helpful. It mainly goes into binary serialization but the concepts are applicable to most any serialization format.

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

The long and short of it is

它的长短是

  • There is no way to add a reliable generic constraint
  • The only way to check and see if an object wasserializable is to serialize it and see if the operation succeeds
  • 没有办法添加可靠的通用约束
  • 检查并查看对象是否可序列化的唯一方法是对其进行序列化并查看操作是否成功

回答by John Saunders

The only way to know if an object is serializable is to try to serialize it.

知道对象是否可序列化的唯一方法是尝试对其进行序列化。

In fact, you were asking how to tell if a type "is serializable", but the actual question will be with respect to objects. Some instances of a type may not be serializable even if the type is marked [Serializable]. For instance, what if the instance contains circular references?

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