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

▼魔方 西西 提交于 2019-12-18 13:52:42

问题


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.

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

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:

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?


回答1:


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):

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:

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.




回答2:


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.

  • http://blogs.msdn.com/jaredpar/archive/2009/03/31/is-it-serializable.aspx

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 was serializable is to serialize it and see if the operation succeeds



回答3:


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?




回答4:


Instead of

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

try

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



来源:https://stackoverflow.com/questions/945495/how-can-i-add-a-type-constraint-to-include-anything-serializable-in-a-generic-me

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!