C# net中DataContract属性和Serializable属性的区别
我正在尝试使用以下方法创建对象的深层克隆C# net中DataContract属性和Serializable属性的区别,c#,.net,serialization,clone,C#,.net,Serialization,Clone,我正在尝试使用以下方法创建对象的深层克隆 public static T DeepClone<T>(this T target) { using (MemoryStream stream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream,
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);
}
}
public static T DeepClone(此T目标)
{
使用(MemoryStream stream=new MemoryStream())
{
BinaryFormatter formatter=新的BinaryFormatter();
序列化(流、目标);
流位置=0;
返回(T)格式化程序。反序列化(流);
}
}
此方法需要序列化的对象,即具有“Serializable”属性的类的对象。我有一个类,它上面有属性“DataContract”,但该方法不使用该属性。我认为“DataContract”也是一种序列化程序,但可能不同于“Serializable”
谁能告诉我两者的区别吗?另外,请让我知道是否有可能创建一个仅具有1个属性的对象的deepclone,该属性同时执行“DataContract”和“Serializable”属性的工作,或者可能是创建deepclone的另一种方式
请帮忙 是工作所必需的
和属性一起使用
您可以使用两个序列化程序的属性装饰一个类。
DataContract
在WCF中使用,因此.NET 3.0+。在.net 2.0或更低版本中,没有DataContract、DataMember
属性,只有Serializable
正如Oded所说,如果你想使用BinaryFormatter,你必须用Serializable来修饰这个类型。我曾经通过反射对一个对象结构进行了一些检查,以找到反序列化所需的所有程序集,并将它们一起序列化以进行引导 只要稍加努力,就可以建立一种类似的深度复制方法。基本上,您需要一个递归方法,该方法通过字典来检测循环引用。在方法内部,您可以检查所有字段,如下所示:
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);
}
}
}
}
private void递归检查(对象输入,
字典处理对象)
{
如果((输入!=null)&&!processedObjects.ContainsKey(输入))
{
Add(输入,true);
列表字段=type.GetFields(BindingFlags.Instance|
BindingFlags.Public | BindingFlags.NonPublic);
foreach(字段中的字段信息字段)
{
对象nextInput=field.GetValue(输入);
if(nextInput是System.Collections.IEnumerable)
{
System.Collections.IEnumerator枚举数=(下一个输入为
GetEnumerator();
while(枚举数.MoveNext())
{
递归检查(enumerator.Current,ProcessedObject);
}
}
其他的
{
递归检查(下一个输入、处理对象);
}
}
}
}
要使其正常工作,您需要添加一个输出对象和类似System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type)
的内容,以创建每个字段值的最浅副本(即使没有复制引用)。最后,您可以使用类似于field.SetValue(输入、输出)
但是,此实现不支持已注册的事件处理程序,反序列化也支持已注册的事件处理程序。此外,如果其类的构造函数需要初始化除设置所有字段以外的任何内容,则层次结构中的每个对象都将被破坏。最后一点仅适用于序列化,如果类具有相应的实现,例如标记为
[ondesearialized]
的方法实现了ISerializable
感谢@Oded的回复。这里只有一个问题。此类正在我的WCF服务中使用。通过添加服务的服务引用,我正在我的消费者项目中使用此服务。每当服务发生更改时,我都需要更新服务引用。当我使用这两个属性并更新服务时,.net会在服务引用的Reference.cs类中创建两个同名的属性。“DataMember”和“Serializable”属性各1个。这将创建一个生成错误。有什么解决方法吗?@samar-据我所知,如果使用了DataContract
,则将忽略Serializable
。我从来没有听说过你的问题。