繁体   English   中英

如何将一种对象类型的对象深复制到共享继承结构的另一种对象类型

[英]How can I deep copy an object of one object type to another object type that share an inheritance structure

我目前正在为HL7消息构建对象模型。 在不深入研究的情况下,我们的基本结构类似于以下内容:

  • 基础对象
    • 中介对象
      • DeepMessage1
      • DeepMessage2
    • MESSAGE1
    • 消息2

我想要一个深层复制/克隆,它将所有类似属性从DeepMessage1复制到DeepMessage2或Message1或Message2。

public class BaseObject
{
    PersonName Name; //A personName includes a first name and last name.
}

public class IntermediaryObject : BaseObject
{
    Accident accident; //An accident codes and a description.
}

public class Message1 : BaseObject
{
    //this class doesn't actually contain any special handling, just used for 
    //easy understanding for the API
}

public class Message2 : BaseObject
{
    DateTime AdmissionDate; //Note the admission date is also contained in
                            //DeepMessage1, but not DeepMessage2
}

public class DeepMessage1 : IntermediaryObject
{
    DateTime AdmissionDate; //Note this property is also contained in Message2 and 
                            //needs to be copied
}

public class DeepMessage2 : IntermediaryObject
{
    DateTime DischargeDate;
}

考虑到这种结构,我希望能够为一个对象与另一个对象共享的每个属性创建一个深层副本。 这另一个问题确实是一个很好的开始,但是最终我不能使用反射,因为那是浅克隆,而序列化需要完全相同的对象。

我最终得到了这段代码,但它仅执行浅表复制。

public T Copy<T>() where T : new()
{
    T destination = new T();
    if (destination is HL7Message)
    {
        foreach (var destinationProperty in destination.GetType().GetProperties())
        {
            foreach (var sourceProperty in this.GetType().GetProperties())
            {
                if (destinationProperty.Name.Equals(sourceProperty.Name))
                {
                    destinationProperty.SetValue(destination, destinationProperty.GetValue(this, null), null);
                }
            }
        }
        return destination;
    }
    else
    {
        throw new InvalidOperationException("The destination copy type is not an HL7Message object");
    }
}

我希望在我的if (destinationProperty.Name.Equals(sourceProperty.Name))块中,我可以尝试对具有特定基本类型(库中所有对象都扩展了)的任何属性调用Copy。 但是,由于无法在运行时确定T,因此无法在该部分中使用“复制”。

我是否只需要为特定对象使用单独的复制类型,并让消息使用复制,还是有办法做到这一点呢?

这是一个用于在对象之间复制属性的完整工具,请看一下:

https://github.com/AutoMapper/AutoMapper/wiki

为了解决这个问题,我最终采用了2层方法。 我没有断言devman提到的地图无法奏效,但是在有限的时间内我无法探究他的解决方案。

首先,我所有的对象都扩展了相同的基础对象(本例为BaseLibraryClass)。 我之所以这样做,是因为每个类都将原始继承INotifyPropertyChanged。 为了处理更改后的属性,我创建了一个继承自所有对象的基础对象。 在这个基类上,我还添加了一个抽象的DeepCopy()方法。 每个对象将通过创建其自身的新实例并在其上分配值来覆盖DeepCopy()方法,如果是自定义属性,则在这些属性上调用DeepCopy()。

Class Cat : BaseLibraryClass
{
    public string Name;
    public Collar MyCollar;

    public override object DeepCopy()
    {
        Cat destination = new Cat();
        Cat.Name = Name;
        Cat.MyCollar = MyCollar.DeepCopy();
    }
}

Class Collar { ... }

现在,在我最初的问题中,将其与反射循环的修改版本结合在一起。 我希望能够执行这种复制的所有对象都继承了相同的基类。 在示例情况下,为BaseCopyObject。

public T CopyObject<T>() where T : new()
{
    T destination = new T();
    if (destination is BaseCopyObject)
    {
        foreach (var destinationProperty in destination.GetType().GetProperties()) //iterate through the properties of the destination object.
        {
            foreach (var sourceProperty in this.GetType().GetProperties()) // iterate through the properties of the source object to determine if the property names match. If they do, copy the value.
            {
                //If we have one of our BaseCopyObjects, then set the value with the DeepCopy() method of that object.
                if (destinationProperty.Name.Equals(sourceProperty.Name))
                {
                    if (typeof(BaseLibraryClass).IsAssignableFrom(destinationProperty.PropertyType))
                    {
                        BaseCopyObject var = (BaseLibraryClass)sourceProperty.GetValue(this, null);
                        if (var != null)
                        {
                            destinationProperty.SetValue(destination, var.DeepCopy(), null);
                        }
                        break;
                    }
                    //If we have a list, get the list and iterate through the list objects.
                    else if (typeof(IList).IsAssignableFrom(destinationProperty.PropertyType))
                    {
                        IList destinationList = (IList)destinationProperty.GetValue(destination, null);
                        destinationList.Clear();
                        IList sourcelist = (IList)destinationProperty.GetValue(this, null);
                        if (sourcelist != null)
                        {
                            foreach (object listItem in sourcelist)
                            {
                                if (listItem is Base)
                                {
                                    BaseLibraryClass n = (BaseLibraryClass)listItem;
                                    destinationList.Add(n);
                                }
                            }
                        }
                        break;
                    }
                    //Finally we get to normal properties. Set those.
                    else
                    {
                        destinationProperty.SetValue(destination, destinationProperty.GetValue(this, null), null);
                        break;
                    }

                }
            }
        }
        return destination;
    }
    else
    {
        throw new InvalidOperationException("The destination copy type is not an BaseLibraryClass object");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM