.net 中 DataContract 属性和 Serializable 属性之间的区别

Posted

技术标签:

【中文标题】.net 中 DataContract 属性和 Serializable 属性之间的区别【英文标题】:difference between DataContract attribute and Serializable attribute in .net 【发布时间】:2011-05-31 12:49:07 【问题描述】:

我正在尝试使用以下方法创建对象的深层克隆。

    public static T DeepClone<T>(this T target)
    
        using (MemoryStream stream = new MemoryStream())
        
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, target);
            stream.Position = 0;
            return (T)formatter.Deserialize(stream);
        
     

此方法需要一个已序列化的对象,即具有“可序列化”属性的类的对象。我有一个类具有属性“DataContract”,但该方法不适用于此属性。我认为“DataContract”也是一种序列化程序,但可能与“Serializable”不同。

谁能告诉我两者之间的区别?另外请让我知道是否可以创建一个只有 1 个属性的对象的深度克隆,该属性可以同时执行“DataContract”和“Serializable”属性的工作,或者可能是创建深度克隆的不同方式?

请帮忙!

【问题讨论】:

【参考方案1】:

Serializable 需要BinaryFormatter 才能工作。

DataContractDataMember 属性与DataContractSerializer 一起使用。

你可以用两个序列化器的属性来装饰一个类。

【讨论】:

感谢@Oded 的回复。这里只有一个问题。此类正在我的 WCF 服务中使用。我通过添加服务的服务引用在我的消费者项目中使用此服务。每当服务发生变化时,我都需要更新服务参考。当我使用这两个属性然后更新服务时,.net 在服务参考的 Reference.cs 类中创建 2 个具有相同名称的属性。 “DataMember”和“Serializable”属性各有 1 个。这会产生构建错误。有什么解决方法吗? @samar - 据我所知,如果使用DataContractSerializable 将被忽略。我从来没有听说过你遇到的问题。【参考方案2】:

DataContract 在 WCF 中使用,因此在 .NET 3.0+ 中使用。在.net 2.0 或更低版本中没有DataContract,DataMember 属性,只有Serializable

正如 Oded 所说,如果你想使用 BinaryFormatter,你必须用 Serializable 装饰类型。

【讨论】:

【参考方案3】:

我曾经通过反射对对象结构进行了一些检查,以找到反序列化所需的所有程序集,并将它们与引导一起序列化。

通过一些工作,您可以构建一种类似的深度复制方法。基本上,您需要一个带有 Dictionary 的递归方法来检测循环引用。在方法中,您检查所有字段,如下所示:

private void InspectRecursively(object input,
    Dictionary<object, bool> processedObjects)

  if ((input != null) && !processedObjects.ContainsKey(input))
  
    processedObjects.Add(input, true);

    List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
        BindingFlags.Public | BindingFlags.NonPublic );
    foreach (FieldInfo field in fields)
    
      object nextInput = field.GetValue(input);

      if (nextInput is System.Collections.IEnumerable)
      
        System.Collections.IEnumerator enumerator = (nextInput as
            System.Collections.IEnumerable).GetEnumerator();

        while (enumerator.MoveNext())
        
          InspectRecursively(enumerator.Current, processedObjects);
        
      
      else
      
        InspectRecursively(nextInput, processedObjects);
      
    
  

要让它工作,你需要添加一个输出对象和类似System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type) 的东西来创建每个字段值的最浅的副本(即使没有复制引用)。最后,您可以使用 field.SetValue(input, output)

之类的内容设置每个字段

但是,此实现不支持已注册的事件处理程序,反序列化也_un_支持。此外,层次结构中的每个对象都将被破坏,如果其类的构造函数需要初始化任何内容而不是设置所有字段。最后一点仅适用于序列化,如果该类具有相应的实现,例如标记为[OnDeserialized] 的方法,实现ISerializable,...。

【讨论】:

以上是关于.net 中 DataContract 属性和 Serializable 属性之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

使用 DataContract 属性时 ProtoBuf.NET 未序列化

DataContract XML 序列化和 XML 属性

我可以同时使用 DataContract 和 Serializable 吗?

如何找出类是不是具有 DataContract 属性?

“Type”属性的DataContract序列化

DataContract with Json.Net