2012-04-22 92 views
1

我想克隆派生类的实例,但不知何故它不能正常工作。克隆方法是:为什么克隆不起作用?

public static T CloneFieldsAndProperties<T>(T input) 
{ 
    T result = (T)Activator.CreateInstance(typeof(T)); 
    PropertyInfo[] listOfProps = typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance); 
    FieldInfo[] listOfFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance); 
    foreach (PropertyInfo prop in listOfProps) prop.SetValue(result, prop.GetValue(input, null), null); 
    foreach (FieldInfo field in listOfFields) field.SetValue(result, field.GetValue(input)); 
    return result; 
} 

正如你所看到的,我加入了很多BindingFlags,因为它不工作。但无济于事。

做一个简单的例子工作:

MyclassA1 a1 = new MyclassA1(); 
MyclassA a = CloneFieldsAndProperties(a1); 
if (a is MyclassA1) Text = "Works"; 

其中:

class MyclassA 
{ 
    public int i; 
} 

class MyclassA1 : MyclassA 
{ 
    public int i1; 
} 

但在我真正的程序没有。真正的课程的类声明很长,所以我不会在这里发布它们。可能是什么问题?

+1

如果它在这个简单的例子中起作用,那么问题可能出在你说你忽略的代码的某个地方? – 2012-04-22 14:05:48

+0

你应该使用'Object.MemberwiseClone'。 – 2012-04-22 14:06:53

+0

@EliArbel只创建一个浅拷贝。我的情况不好。但是,谢谢。 – ispiro 2012-04-22 14:09:48

回答

2

如果你需要一个浅克隆,简单地使用Object.MemberwiseClone。如果您需要深度克隆,请序列化并反序列化您的对象(例如,使用BinaryFormatterDataContractSerializer)。这将处理周期和交叉引用等问题。

3

很久以前我有同样的问题。对于我来说,唯一真正的解决方案是大量使用Google进行序列化和反序列化。这不是一个坏的解决方案,你失去唯一的性能一点点,只是做这样的:

添加此标记到类:

[Serializable()] 
public class a 
{ 

} 

然后你就可以创建这样一个功能:

public object Clone() 
{ 
    IO.MemoryStream mem = new IO.MemoryStream(); 
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter form = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
    form.Serialize(mem, this); 
    mem.Position = 0; 
    return form.Deserialize(mem); 
} 
0

这将工作和可能比序列化方法更快:

代码:

using System; 

namespace Cloning 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived() { property = 1, field = 2, derivedProperty = 3, derivedField = 4 }; 
      Base b = new Derived(d); 

      // Change things in the derived class. 
      d.property = 5; 
      d.field = 6; 
      d.derivedProperty = 7; 
      d.derivedField = 8; 

      // Output the copy so you know it's not shallow. 
      Console.WriteLine((b as Derived).property); 
      Console.WriteLine((b as Derived).field); 
      Console.WriteLine((b as Derived).derivedProperty); 
      Console.WriteLine((b as Derived).derivedField); 

      Console.ReadLine(); 
     } 

     class Base 
     { 
      public int property { get; set; } 
      public int field; 
     } 

     class Derived : Base 
     { 
      public Derived() { } 

      public Derived(Derived d) 
      { 
       // Perform the deep copy here. 
       // Using reflection should work, but explicitly stating them definitely 
       // will, and it's not like it's not all known until runtime. 
       this.property = d.property; 
       this.field = d.field; 
       this.derivedProperty = d.derivedProperty; 
       this.derivedField = d.derivedField; 
      } 

      public int derivedProperty { get; set; } 
      public int derivedField; 
     } 

    } 
} 

测试:

http://goo.gl/pQnAL

输出:

1 
2 
3 
4 

评论:

我真的想象,这将超过只是一个微不足道的情况下,但也许不行:

public static T CloneFieldsAndProperties<T>(T input) 
{ 
    T result = (T)Activator.CreateInstance(input.GetType()); 

    PropertyInfo[] properties = input.GetType().GetProperties(); 
    FieldInfo[] fields = input.GetType().GetFields(); 

    foreach (PropertyInfo property in properties) 
     property.SetValue(result, property.GetValue(input, null), null); 
    foreach (FieldInfo field in fields) 
     field.SetValue(result, field.GetValue(input)); 

    return result; 
}