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