DataContractSerializer 和 Serializable 的问题

Posted

技术标签:

【中文标题】DataContractSerializer 和 Serializable 的问题【英文标题】:Problems with the DataContractSerialiser and Serializable 【发布时间】:2011-07-13 08:32:52 【问题描述】:

我有一些来自 .Net 2.0 程序集的类。这些类标有 Serializable。

在我的项目中,我在我的 Classes 中使用这些类,它们用 DataContract(IsReference=true) 和 DataMember 标记。

现在我遇到了问题,它使用 DataContractSerialiser 序列化我的 .Net 2.0 类的私有字段,这将不起作用。但是当我使用 XMLSerialiser 时,我不能使用 IsReference,所以我也不能这样做。

是否有一个简单(简单)的解决方案?也许有人有自己的支持引用的 XMLSerializer?

这是我的一些代码:

[DataContract(IsReference = true)]
public class ConnectionConfig: INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(String info)
    
        if (PropertyChanged != null)
        
            PropertyChanged(this, new PropertyChangedEventArgs(info));
            PropertyChanged(this, new PropertyChangedEventArgs("ObjectAsString"));
        
    

    private PLCConnectionConfiguration _configuration;
    [DataMember]
    public PLCConnectionConfiguration Configuration
    
        get  return _configuration; 
        set  _configuration = value; NotifyPropertyChanged("Configuration"); 
    

其中 PLCConnectionConfiguration 来自 .NET 2.0 程序集,并用 [Serializeable] 修饰

【问题讨论】:

你的意思是你不希望它序列化私有字段(通常 DataContractSerializer 只序列化公共属性)?或者当他尝试但失败时你得到一个错误? 是的,我不想序列化私有字段,但是 DataContractSerializer 在用 [Serializable] 修饰的类上执行此操作 本例中的PLCConnectionConfiguration 是什么? 这是来自另一个议会的课程,我无法更改。这个类是可序列化的,但不能使用 DataContractSerializer,因为它序列化了私有字段! (这是我的问题!) 【参考方案1】:

[DataContract] 注释一个类型应该足以告诉它寻找标记为 [DataMember] 的成员 - 但听起来你可能有数据合同和普通对象的组合。

如果您严格需要 xml,我在这里的建议是编写一组 DTO 类型并在图形模式下使用 DCS。这可能需要在您的对象模型和 DTO 之间进行一些映射;但这通常不是什么大问题。另请注意,图形模式下的 DCS 不是典型的 xml 输出 - 它与 XmlSerializer 的输出会有很大不同。

如果您只需要序列化任意类型(xml 不是问题),那么 protobuf-net 当前的 experimental 切割支持所有这些场景;它将处理对象引用,它允许您使用带注释的类型和普通类型(您只需要告诉它如何)。如果这是一个选项,或许可以提供一个您的模型的基本示例,我也许可以填补一些空白。

【讨论】:

我在问题中放了一个我的班级示例!【参考方案2】:

您应该从您的域模型中抽象出 WCF 数据契约。将数据合同视为您希望在服务中返回的模型的视图。

使用[DataContract] 属性注释您的数据合同,并使用[DataMember] 属性注释您要公开的所有属性。如果有您不想返回的属性,请不要使用[DataMember] 属性对其进行注释。

如果您希望您的域模型是 XmlSerializable,请使用 [Serializable] 属性注释该类。

它可能需要一些额外的输入和转换,但总体而言更清晰。

【讨论】:

您还可以使用 AutoMapper - automapper.codeplex.com 之类的工具减少从域模型对象转换为数据合约对象所花费的时间【参考方案3】:

也许您可以使用 XmlSerializer 并指定 XmlAttributeOverrides 来忽略您不感兴趣的私有字段:

var overrides = new XmlAttributeOverrides();
overrides.Add(typeof(PLCConnectionConfiguration), <name of private field to exclude>, new XmlAttributes  XmlIgnore = true );
...
var serialiser = new XmlSerializer(typeof(ConnectionConfig), overrides);

您显然还必须将 ConnectionConfig 标记为 Serializable 并将 [XmlIgnore] 添加到 _configuration 字段。

【讨论】:

使用 XMLSerializer 可以工作,但我想使用 DataContractSerializer,因为它支持引用! 我现在用 XMLSerializer 解决了这个问题,并在序列化后重建了我的引用,但我不喜欢这个解决方案!

以上是关于DataContractSerializer 和 Serializable 的问题的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 DataContractSerializer 自定义序列化

DataContractSerializer 没有反序列化所有变量

XmlSerializer, DataContractSerializer 和 BinaryFormatter区别与用法分析

使用 DataContractSerializer 从 WCF 服务接收到的序列化响应

使用 DataContractSerializer 时与 XmlArrayItem 等效的是啥? [复制]