如何制作一个派生自List<T>的对象的深度拷贝

3
我有以下类:
public partial class AuthorizationSetObject
{
   public AuthorizationObjectList AuthorizationObjects { get; set; }
}

public partial class AuthorizationObject
{
   public string Text { get; set; }
}

public partial class AuthorizationObjectList : List<AuthorizationObject>
{
}

我需要现在一个AuthorizationSetObject的深拷贝。我该怎么做?
我尝试过这样:
public static bool CopyProperties(object source, object target)
{
    var customerType = target.GetType();
    foreach (var prop in source.GetType().GetProperties())
    {
        var propGetter = prop.GetGetMethod();
        if (propGetter != null)
        {
            PropertyInfo pi = customerType.GetProperty(prop.Name);
            if (pi != null)
                {
                var propSetter = pi.GetSetMethod();
                if (propSetter != null)
                {
                    var valueToSet = propGetter.Invoke(source, null);
                    propSetter.Invoke(target, new[] { valueToSet });
                }
            }
        }
    }
    return true;
}

问题在于AuthorizationObjectList不是一个真正的深拷贝。如果我在深拷贝后更改目标的“Text”属性,则源的“Text”也会被更改。
可能需要实现类似于“pi.PropertyType.BaseType.IsGenericType”的内容,然后做些其他的事情...但是什么呢?
有人有想法吗?

4
如何在复制泛型列表时保持原列表不被修改?问题描述:如何在复制泛型列表时,确保对新列表的修改不会反映到原始列表中。 解决方法:可以使用LINQ的ToList() 方法来创建原列表的副本,该副本与原列表独立,对其进行修改不会影响原列表。 代码示例:List originalList = new List(); // 添加元素到原始列表 List copyList = originalList.ToList(); // 对复制的列表进行修改 // 此时修改copyList不会影响originalList - Hardrada
1
在不提供值语义的语言中进行深拷贝的典型解决方案是将对象序列化,然后在另一个位置反序列化。 - Alex
1
因为AuthorizationSetObject是你自己的类,所以你可以实现IClonable接口。 - Hamlet Hakobyan
可能是如何在C#中克隆通用列表?的重复问题。 - Matthew Strawbridge
你可以使用 struct 而不是 class,因为它们是按值传递而不是按引用传递。我建议你深入研究它们之间的区别,因为这是你应该了解的 C# 核心原则。你正在过度设计你的问题,并使其看起来解决方案非常复杂。通常情况下,框架没有实现某些功能的原因是因为你可能处于代码异味的情况下,只需要稍微重构一下即可。 - Piotr Kula
1个回答

0

对你的问题发表的评论都指向了正确的方向。问题在于,在这一行中

propSetter.Invoke(target, new[] { valueToSet });

valueToSet是一个引用,这意味着您将一个对同一对象的引用添加到列表中。现在ICloneable就派上用场了。如果valueToSet的类型实现了ICloneable,则可以使用

propSetter.Invoke(target, new[] { valueToSet.Clone() });

相反,使用“instead”方法将生成此实例的新深层副本。


非常感谢您的回答。它是如何确切地工作的?valueToSet 是对象类型,没有已知的克隆方法。需要转换为 ICloneable 吗? - Marc
你能使用你自己实现的更专业化的东西吗? - Alexander Schmidt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接