Неглубокое копирование из унаследованных классов

Итак, у меня есть абстрактный базовый класс Product, класс KitItem, который наследует Product, и класс PackageKitItem, который наследует KitItem. т.е.

Product
KitItem : Product
PackageKitItem : KitItem

У меня загружены KitItems, и мне нужно загрузить коллекцию PackageKitItems, которые фактически являются мелкими копиями KitItems.

В настоящее время мы делаем то, что мне кажется хакерской мелкой копией в конструкторе продукта, например так:

public Product(Product product)
        {
            FieldInfo[] fields = product.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

            // copy each value over to 'this'
            foreach (FieldInfo fi in fields)
                fi.SetValue(this, fi.GetValue(product));
        }

Я попытался настроить копию на KitItem следующим образом:

public KitItem ShallowCopy()
        {
            return (KitItem)this.MemberwiseClone();
        }

и называя это так:

PackageKitItem tempPackKitItem = (PackageKitItem)packKitItem.ShallowCopy();

но я получаю недопустимый бросок. Я ищу идеи для лучшего способа сделать это.


person Echostorm    schedule 12.11.2008    source источник
comment
Если packKitItem является KitItem, то использование MemberwiseClone по-прежнему будет возвращать KitItem.   -  person Marc Gravell    schedule 12.11.2008
comment
Нет, клон находится на KitItem, я пытаюсь инициализировать packagekiitem, и в этом суть проблемы, это не сработает.   -  person Echostorm    schedule 12.11.2008
comment
Вы не должны упаковывать котят как продукты, это жестоко!   -  person Steven A. Lowe    schedule 12.11.2008


Ответы (3)


Проблема заключается в том, что, поскольку ShallowCopy() является членом KitItem, MemberwiseClone() просто копирует поля KitItem и возвращает KitItem, даже если исходный объект является PackageKitItem.

Я думаю, что вам нужно сделать в этом случае, добавьте в KitItem:

public virtual KitItem ShallowCopy()        
{            
  return (KitItem) this.MemberwiseClone();        
}

и в PackageKitItem:

public override KitItem ShallowCopy()        
{            
    return (PackageKitItem) this.MemberwiseClone();        
}

Таким образом, вы получите правильный вызов MemberwiseClone() в зависимости от объекта, который вы пытаетесь применить к ShallowCopy().

Если вы хотите пойти дальше, вы можете определить ShallowCopy() в Product (возвращая Product), а затем иметь переопределенные версии в KitItem и PackageKitItem, каждая из которых возвращает свою соответствующую поверхностную копию.

person TAG    schedule 15.11.2008

Как ни странно, я не получил ошибки при выполнении этого в Visual Studio 2008. Я отправляю код, чтобы вы могли видеть, что я упускаю или что я предполагаю неправильно. Я предполагаю, что проблема в одном из участников класса, которого вы не опубликовали.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            PackageKitItem PKI = new PackageKitItem();
            PKI.ID      = 1;
            PKI.KitName = "2";
            PKI.Name    = "3";
            PKI.Package = 4;

            PackageKitItem tempPackKitItem = (PackageKitItem)PKI.ShallowCopy();

        }
    }

}

public class Product
{
    public int ID;
    public string Name;

    public Product()
    {
    }

    public Product(Product product)
    {
        FieldInfo[] fields = product.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        // copy each value over to 'this'
        foreach (FieldInfo fi in fields)
            fi.SetValue(this, fi.GetValue(product));
    }


}

public class KitItem:Product
{
    public string KitName;
    public KitItem ShallowCopy()
    {
        return (KitItem)this.MemberwiseClone();
    }

}

public class PackageKitItem : KitItem
{
    public int Package;

}
person RS Conley    schedule 12.11.2008

В конструкторе продукта вы уже выполняете некоторую форму поверхностного копирования, не так ли? Если вы не перезаписали свой конструктор, вы сможете просто создать новый PackageKitItem, который получает KitItem в качестве параметра.

PackageKitItem tempPackKitItem = new tempPackKitItem(kitItem);

Возможно, я просто неправильно понял ваш вопрос.

person Leonardo Herrera    schedule 12.11.2008