为什么DataContractSerializer不起作用?

时间:2012-04-20 00:50:39

标签: datacontractserializer

我不知道如何通过DataContractSerialize序列化对象。 这是我的代码:

    public static string DataContractSerialize(object target)
    {
        var formatter = new DataContractSerializer(target.GetType());
        using (var stream = new MemoryStream())
        {
            formatter.WriteObject(stream, target);
            stream.Position = 0;
            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }

和实体

[Serializable, DataContract(Namespace = "CommunicationModel.Entity")]
[KnownType(typeof(Message))]
[KnownType(typeof(int))]
[KnownType(typeof(string))]
[KnownType(typeof(Type))]
[KnownType(typeof(object))]
public class Message : IDisposable
{
    public Message(string stringInfo)
    {
        MessageValue = stringInfo;
        MessageType = typeof (string);
    }

    public Message(int intInfo)
    {
        MessageValue = intInfo;
        MessageType = typeof (int);
    }
    [DataMember]
    public Type MessageType { get; private set; }
    [DataMember]
    public object MessageValue { get; private set; }

    #region Implementation of IDisposable

    public void Dispose()
    {
    }

    #endregion
}

当我像这样运行DataContractSerialize时:

var sData = SerializerHelper.DataContractSerialize(msg);

它会引发异常。我该怎么办?

1 个答案:

答案 0 :(得分:0)

首先,您不能拥有[Serializable]和[DataContract]的类型。这是不推荐的,没有意义。只需要[DataContract]。有关原因的详细信息,请参阅this post on the data contract programming model

无论如何,这里的问题是你实际上是在尝试序列化RuntimeType,因为MessageType被表示为RuntimeType。 RuntimeType是一个内部类,它是Type的子类,并且不是公共的,因此您无法有意将其称为已知类型。有关RuntimeType是什么以及它的原因,请参阅What's the difference between System.Type and System.RuntimeType in C#?

所以,你有两个选择:

  • 考虑添加一个采用静态方法名称的KnownTypes属性。从静态方法中,您可以返回您真正想要的各种类型,包括使用反射时可能的RuntimeType。

  • 推荐的选项是使MessageType成为一个TypeHandle(一个RuntimeTypeHandle。)这样做的好处是你可以让RuntimeTyepHandle成为一个已知的类型,因为它是公共的。它也可以像任何其他类型一样进行序列化和反序列化。请参阅this excellent blog post我的意思。