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
。我从来没有听说过你的问题。