Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 克隆可观察收集_C# - Fatal编程技术网

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));
}