C# 克隆可观察收集
我有一个带有C# 克隆可观察收集,c#,C#,我有一个带有ObservableCollection和其他属性的类。 所以它看起来有点像这样: public class A { public int Id { get; set; } ... public object AValue {get; set;} } 我想克隆这个类的对象AValue属性可以是ObservableCollection或其他对象。当AValue属于ObservableCollection类型,并且我试图向其中添加一些对象时,克隆似乎与原始对象具有相同
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");
}
}
私有对象克隆(对象obj)
{
var t=obj.GetType();
if(obj==null)
返回null;
if(t.IsValueType | | t==typeof(string))
{
返回obj;
}
else if(t.IsGenericType)
{
如果(对象是IList)
{
var c=类型(可观测采集);
var cType=type.GetGenericArguments().First();
var gType=c.MakeGenericType(cType);
var newC=(IList)Activator.CreateInstance(gType);
foreach(变量项在(IEnumerable)对象中)
新增(项目);
返回newC;
}
}
else if(t.IsClass)
{
object objV=Activator.CreateInstance(类型);
FieldInfo[]fields=t.GetFields(BindingFlags.Public|
BindingFlags.NonPublic | BindingFlags.Instance);
foreach(字段中的字段信息字段)
{
object fieldV=field.GetValue(obj);
如果(fieldValue==null)
继续;
field.SetValue(objV,克隆(fieldV));
}
返回obj;
}
抛出新ArgumentException(“未知类型”);
}
}
编辑
谢谢你的回答。
我添加了你的代码@Sefe,但仍然不起作用。我知道其他类型不会克隆,但我想先使用列表。我不知道哪里出了错。我得到一个类对象,然后克隆对象并将一个类对象发送到dialogbox。我更改了克隆和原始的集合和属性。
将IClonable接口添加到列表的泛型类型就足够了
ObservableCollection<B> = new ObservableCollection<B>();
public class B: Base, ICloneable
{
...
public object Clone()
{
return this.MemberwiseClone();
}
ObservableCollection=新的ObservableCollection();
公共B类:基本、可克隆
{
...
公共对象克隆()
{
返回此.MemberwiseClone();
}
}
泛型类型可以从另一个类继承很重要吗?您正在克隆集合,但没有克隆其项。要创建集合的深度克隆,还需要克隆项目(如果可能): 使用
ICloneable
接口是.NET framework中的内置方式,您可以期望framweork方法在必要时识别它。因此,这将是首选的方式。如果您想重用自己现有的Clone
方法,可以递归调用它:
foreach (var item in (IEnumerable)obj) {
newC.Add(Clone(item));
}
更新(解决问题的编辑):
使用MemberwiseClone
时,所有字段和事件都将传输到克隆MemberwiseClone
创建浅层副本,以便传输字段和分配的事件处理程序。因此,如果您有包含其他引用类型的字段,这些字段将不会被克隆(即使它们是ICloneable
)。此外,分配给原始的事件处理程序也将分配给克隆
您的
ICloneable.Clone
方法必须注意将克隆置于有效状态。由于有效内容因情况而异,因此.NET framework中没有自动深度克隆。调用MemberwiseClone
通常是一个很好的开始,但随后必须处理包含的对象、事件处理程序等,才能将浅克隆“升级”到深克隆。代码中可能存在错误。不是列表的泛型类型呢?它们不会被克隆。@Sefe我也遇到了这个问题,但在这种情况下抛出了一个异常,这很好(可能是一个NotImplementedException,但仍然是)。当我需要经常深度复制集合时,我为容器编写了一个扩展。签名为public static TContainer CloneDeep(此TContainer r),其中T:ICloneable,其中TContainer:ICollection,new()
。普通泛型都有一个new()
,因此它适用于常见的列表等。该函数只需迭代源容器,然后Clone()
将元素添加到克隆容器中。请注意,字典需要进行特殊处理,以克隆键和值。
foreach (var item in (IEnumerable)obj) {
newC.Add(Clone(item));
}