【问题标题】:Deep Cloning of Collections(Key/Value Pair) using Reflection使用反射深度克隆集合(键/值对)
【发布时间】:2017-07-12 18:01:08
【问题描述】:

我正在使用下面的类来做没有序列化的深度克隆。

  public class AbstractClone
{

    public AbstractClone Clone()
    {
        Type typeSource = this.GetType();
        AbstractClone tObject = (AbstractClone)FormatterServices.GetUninitializedObject(typeSource);

        PropertyInfo[] propertyInfo = typeSource.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        foreach (PropertyInfo property in propertyInfo)
        {
            if (property.CanWrite)
            {

                if (property.PropertyType.IsValueType || property.PropertyType.IsEnum || property.PropertyType.Equals(typeof(System.String)))
                {
                    property.SetValue(tObject, property.GetValue(this, null), null);
                }
                else
                {
                    object objPropertyValue = property.GetValue(this, null);

                     if (objPropertyValue == null)
                    {
                        property.SetValue(tObject, null, null);
                    }
                    else
                    {
                        property.SetValue(tObject, ((AbstractClone)objPropertyValue).Clone(), null);
                    }
                }
            }

        }
        return tObject;
    }
}

我继承了所有需要克隆的类。

这适用于除键值对或 SortedList、Dictionary 等集合之外的所有对象

谁能建议一种方法来克隆 KeyValue 对,例如 Dictionary 的 SortedList。

【问题讨论】:

    标签: c# reflection cloning


    【解决方案1】:

    由于您已经在此处强制执行继承规则,只有从 AbstractClone 派生的类才会被深度克隆,您可以改为在其上粘贴 [Serializable] 并摆脱强制继承。序列化和反序列化是一种有保证的深度克隆技术。

    [Serializable]
    class T
    {
        public int F1 { get; set; }
        public int F2 { get; set; }
    }
    
    T CloneT(T obj)
    {
        var ms = new MemoryStream();
    
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, o);
    
        ms.Position = 0;
    
        var clone = (T)formatter.Deserialize(ms);
    
        return clone;
    }
    
    var o = new T { F1 = 5, F2 = 12 };
    CloneT(o);
    

    【讨论】:

      【解决方案2】:

      深度复制是一项艰巨的任务。首先,您的解决方案可能根本无法使用,因为它需要从您的类型继承,并且您不能继承 3rd 方类。第二个问题是它不是很深:您将复制所有引用:

      class Employee
      {
        public string Name {get; set;}
        public Position Position {get; set;}
      }
      class Position
      {
        public string Name {get;set;}
        public int ID {get;set;}
      }
      

      如果您更改原始对象中Position 属性的Name 属性,您将在副本中看到这些更改。 如果您尝试升级您的解决方案以递归地运行属性,您将不得不处理循环引用。

      但是,这项工作已经完成,您只需寻找现成的解决方案,例如,this one

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-09
        • 2019-09-06
        • 1970-01-01
        • 2013-07-17
        • 2012-06-05
        • 2013-09-06
        相关资源
        最近更新 更多