使用 DataContractSerializer 自定义序列化

Posted

技术标签:

【中文标题】使用 DataContractSerializer 自定义序列化【英文标题】:Custom serialization with DataContractSerializer 【发布时间】:2011-03-10 12:53:19 【问题描述】:

我目前正在为我的 DataSets 使用包装类,以实现自定义序列化。我想使用DataContractSerializer(更像是必须使用它)但仍然支持自定义序列化。问题是 [DataContract][Serializable] 属性似乎相处得不太好......我怎么能覆盖序列化,并支持 BOTH DataContract 和 ISerializable 序列化? 这里带来了包装DataSet类的代码:

[Serializable()]    
[System.Runtime.InteropServices.ComVisible(false)]
public class TestDatasetWrapper : TestDataSet, ISerializable

    public TestDatasetWrapper()
        : base()
    

    protected TestDatasetWrapper(SerializationInfo info, StreamingContext context)
    
        SerializationHelper.DeserializeTypedDataSet(info, this);
    

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    
        SerializationHelper.AddTypedDataSetObjectData(info, this);
    

谢谢!

【问题讨论】:

【参考方案1】:

DataContractAttribute 和 SerializableAttribute 可以一起使用。这里的好处是,您也不需要使用单独的序列化程序。 DataContractSerialzer 是一个 XmlObjectSerializer,它本身支持 [Serializable]。例如:

[Serializable]
public class TestClass

    public string Name  get; set; 



    var formatter = new DataContractSerializer(typeof(TestClass));
    using (var stream = new MemoryStream())
    
        var instance = new TestClass  Name = "Matt" ;
        formatter.WriteObject(stream, instance);

        stream.Seek(0, SeekOrigin.Begin);

        var second = (TestClass) formatter.ReadObject(stream);
        Console.WriteLine(second.Name);
    

输出:“马特”

仅使用一个 SerializableAttribute 属性,我们就可以使用 DataContractSerializer 成功地序列化和反序列化对象...

使用 ISerializable,我们可以做同样的事情:

[Serializable]
public class TestClass2 : ISerializable

    public TestClass2()  
    protected TestClass2(SerializationInfo info, StreamingContext context)
    
        Name = info.GetString("name").ToUpper();
    

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    
        info.AddValue("name", Name);
    

    public string Name  get; set; 



    var formatter = new DataContractSerializer(typeof(TestClass2));
    using (var stream = new MemoryStream())
    
        var instance = new TestClass2  Name = "Matt" ;
        formatter.WriteObject(stream, instance);

        stream.Seek(0, SeekOrigin.Begin);

        var second = (TestClass2)formatter.ReadObject(stream);
        Console.WriteLine(second.Name);
    

输出:“MATT”

并带有 DataContractAttribute:

[DataContract, Serializable]
public class TestClass3

    public int Age  get; set; 

    [DataMember]
    public string Name  get; set; 



    var formatter = new DataContractSerializer(typeof(TestClass3));
    using (var stream = new MemoryStream())
    
        var instance = new TestClass3  Name = "Matt", Age = 26 ;
        formatter.WriteObject(stream, instance);

        stream.Seek(0, SeekOrigin.Begin);

        var second = (TestClass3)formatter.ReadObject(stream);
        Console.WriteLine(second.Name);
        Console.WriteLine(second.Age);
    

输出:“马特”

输出:0

当 DataContractSerializer 遇到具有 DataContractAttribute 的类型时,它将使用该类型而不是将序列化传递给其处理 SerializableAttribute 和 ISerializable 接口的基类型。

如果您遇到问题,是与序列化有关,还是与反序列化有关,或两者兼而有之?

【讨论】:

您的所有 3 个样本似乎都缺少函数签名行。

以上是关于使用 DataContractSerializer 自定义序列化的主要内容,如果未能解决你的问题,请参考以下文章

使用 DataContractSerializer 时设置属性的初始值

使用 DataContractSerializer 和 XmlDictionaryWriter 序列化 JObject 后崩溃

在原语列表上使用 DataContractSerializer 的自定义元素名称

使用 DataContractSerializer 的接口中的显式类型

使用 DataContractSerializer 序列化没有命名空间的对象

如何使用 DataContractSerializer 从 XMLDocument 的单个节点反序列化?