克隆ObservableCollection

时间:2017-02-08 10:07:50

标签: c#

我有ObservableCollection课程和其他属性。 所以看起来有点像这样:

public class A
{
   public int Id { get; set; }
   ...
   public object AValue {get; set;}
}

我想克隆这个类的对象。 AValue属性可以是ObservableCollection或其他对象。当AValue是ObservableCollection类型并且我试图向它添加一些对象时,似乎克隆具有与原始相同的对象。如果我只将克隆方法用于AValue属性,而不是类A的对象,则可以使用。要克隆我试图使用的对象:

 private object Clone(object obj)
    {
        var t = obj.GetType();

        if (obj == null)
            return null;

        if (t.IsValueType || t == typeof(string))
        {
            return obj;
        }
        else if (t.IsGenericType)
        {
            if (obj is IList)
            {
                var c= typeof(ObservableCollection<>);
                var cType = type.GetGenericArguments().First();
                var gType = c.MakeGenericType(cType);
                var newC = (IList)Activator.CreateInstance(gType);

                foreach (var item in (IEnumerable)obj)
                    newC.Add(item);

                return newC;
            }
        }
        else if (t.IsClass)
        {
            object objV = Activator.CreateInstance(type);
            FieldInfo[] fields = t.GetFields(BindingFlags.Public |
                        BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                object fieldV = field.GetValue(obj);
                if (fieldValue == null)
                    continue;
                field.SetValue(objV, Clone(fieldV));
            }
            return obj;
        }
        throw new ArgumentException("Unknown type");
    }
}

修改 谢谢你的回答。 我添加了你的代码@Sefe但它仍然不起作用。我知道其他类型没有克隆,但我想首先使用列表。我不知道哪里出错了。我得到A类对象然后克隆对象并将A类对象发送到对话框。我更改了克隆和原始的集合和属性是相同的。 它应该将IClonable接口添加到通用类型的列表

 ObservableCollection<B> = new  ObservableCollection<B>();

public class B: Base, ICloneable
{
  ...
  public object Clone()
  {
    return this.MemberwiseClone();
  }

}

泛型类型可以从另一个类继承吗?

1 个答案:

答案 0 :(得分:4)

您正在克隆该集合,但您没有克隆其项目。要创建集合的深层克隆,您还需要克隆项目(如果可能):

foreach (var item in (IEnumerable)obj) {
    ICloneable cloneable = item as ICloneable;
    if (cloneable != null) {
        newC.Add(cloneable.Clone());
    }
    else {
        newC.Add(item);
    }
}

使用ICloneable接口是.NET框架中的内置方式,您可以期望framweork方法在必要时识别它。所以这将是首选方式。如果您想重用自己现有的Clone方法,可以递归调用它:

foreach (var item in (IEnumerable)obj) {
    newC.Add(Clone(item));
}

更新(要解决问题的编辑):

当您使用MemberwiseClone时,所有字段和事件都将转移到克隆。 MemberwiseClone创建副本,因此会传输字段和分配的事件处理程序。因此,如果您的字段包含其他引用类型,则不会克隆这些类型(即使它们是ICloneable)。此外,分配给orginal的事件处理程序也将分配给克隆。

您的ICloneable.Clone方法必须注意将克隆置于有效状态。因为什么是有效的不同情况,.NET框架中没有自动深度克隆。调用MemberwiseClone通常是一个良好的开端,但您必须将包含的对象,事件处理程序等添加到&#34;升级&#34;你的浅层克隆到深层克隆。