2010-03-10 124 views
6

虽然使用此代码序列化对象:克隆整个对象图

public object Clone() 
{ 
    var serializer = new DataContractSerializer(GetType()); 
    using (var ms = new System.IO.MemoryStream()) 
    { 
     serializer.WriteObject(ms, this); 
     ms.Position = 0; 
     return serializer.ReadObject(ms); 
    } 
} 

我注意到,它不会复制的关系。 有什么办法可以做到这一点?

+0

我发现同样的,它可能会进入一些层次,但大多数情况下,最终会产生一个局部和无用的图形。 – leppie 2010-03-10 13:12:46

+0

@leppie - 它可以完成,虽然; - p – 2010-03-10 13:26:18

回答

16

简单地使用接受preserveObjectReferences的构造函数重载,并将其设置为true:

using System; 
using System.Runtime.Serialization; 

static class Program 
{ 
    public static T Clone<T>(T obj) where T : class 
    { 
     var serializer = new DataContractSerializer(typeof(T), null, int.MaxValue, false, true, null); 
     using (var ms = new System.IO.MemoryStream()) 
     { 
      serializer.WriteObject(ms, obj); 
      ms.Position = 0; 
      return (T)serializer.ReadObject(ms); 
     } 
    } 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     Bar bar = new Bar(); 
     foo.Bar = bar; 
     bar.Foo = foo; // nice cyclic graph 

     Foo clone = Clone(foo); 
     Console.WriteLine(foo != clone); //true - new object 
     Console.WriteLine(clone.Bar.Foo == clone); // true; copied graph 

    } 
} 
[DataContract] 
class Foo 
{ 
    [DataMember] 
    public Bar Bar { get; set; } 
} 
[DataContract] 
class Bar 
{ 
    [DataMember] 
    public Foo Foo { get; set; } 
} 
+0

Duh!我应该寻找更多的提示! :) – leppie 2010-03-10 13:39:50

+0

这应该是最好的方式,因为我可以看到... thanx马克,但我有一个Object.Object2.Object3的问题,这可能是串行器的问题? – 2010-03-10 13:47:37

1

可以使用[DataContract]注释您的类,或者在DatacontractSerializer的构造函数中添加您的子类型。

var knownTypes = new List<Type> {typeof(Class1), typeof(Class2), ..etc..}; 
var serializer = new DataContractSerializer(GetType(), knownTypes); 
+0

Thanx,这看起来也工作;) – 2010-03-10 13:48:00

0

在序列化/反序列化步骤中,需要二进制序列化程序来保留对象标识。

+0

是的,但我使用SqlMetal创建类和触发器/序列化:单向。对造成的不便表示歉意。 – 2010-03-10 13:16:26

+0

我无法理解您的评论与我的回答有何关系...?看看Darin Dimitrov提供的代码示例 – Seb 2010-03-10 13:18:52

+1

对不起@Seb,但这是不正确的。 DataContractSerializer *可以*复制适当的图形,而不是二进制串行器。相反,所有二进制序列化器*都不一定能够复制图形。图形支持和二进制输出是正交的概念。 – 2010-03-10 13:25:42

1

要执行你可以考虑使用一个二进制序列深克隆:

public static object CloneObject(object obj) 
{ 
    using (var memStream = new MemoryStream()) 
    { 
     var binaryFormatter = new BinaryFormatter(
      null, 
      new StreamingContext(StreamingContextStates.Clone)); 
     binaryFormatter.Serialize(memStream, obj); 
     memStream.Seek(0, SeekOrigin.Begin); 
     return binaryFormatter.Deserialize(memStream); 
    } 
}