克隆ObservableCollection

dMi*_*lan 2 c#

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

public class A
{
   public int Id { get; set; }
   ...
   public object AValue {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

我想要此类的克隆对象。AValue属性可以是ObservableCollection或其他对象。当AValue类型为ObservableCollection时,我尝试向其中添加一些对象,似乎克隆具有与原始对象相同的对象。如果我仅将克隆方法用于AValueProperty,而不是对类对象使用,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");
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑 感谢您的回答。我添加了您的代码@Sefe,但仍然无法正常工作。我知道其他类型不会克隆,但我想先用列表来完成。我不知道哪里出错了。我得到一个A类对象,然后克隆对象并将A类对象发送到对话框。我更改集合,克隆和原始的属性相同。将IClonable接口添加到列表的通用类型就足够了

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

public class B: Base, ICloneable
{
  ...
  public object Clone()
  {
    return this.MemberwiseClone();
  }
Run Code Online (Sandbox Code Playgroud)

}

泛型类型可以从另一个类继承是否重要?

Sef*_*efe 5

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

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

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

foreach (var item in (IEnumerable)obj) {
    newC.Add(Clone(item));
}
Run Code Online (Sandbox Code Playgroud)

更新(以解决问题的修改):

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

您的ICloneable.Clone方法必须注意将克隆置于有效状态。由于有效情况因情况而异,因此.NET框架中没有自动深度克隆。调用MemberwiseClone通常是一个好的开始,但是您必须先处理包含的对象,事件处理程序等,才能将浅克隆“升级”为深克隆。