views:

332

answers:

3

Ok so I have an abstract base class called Product, a KitItem class that inherits Product and a PackageKitItem class that inherits KitItem. ie.

Product
KitItem : Product
PackageKitItem : KitItem

I have my KitItems loaded and I need to load up a collection of PackageKitItems which are, effectively, shallow copies of KitItems.

Currently we are doing what feels to me a hacky shallow copy in the Product constructor like so:

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

I've tried setting up a copy on KitItem like so:

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

and calling it thus:

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

but I get an invalid cast. I'm looking for ideas for the best way to accomplish this.

A: 

In your Product constructor you are already doing some form of shallow copy, aren't you? If you haven't overwritten your constructor, then you should be able to just create a new PackageKitItem that receives a KitItem as its parameter.

PackageKitItem tempPackKitItem = new tempPackKitItem(kitItem);

Maybe I just misunderstood your question.

Leonardo Herrera
A: 

Strangely I didn't get an error doing this on Visual Studio 2008. I am posting the code so you can see what I am missing or what I am assuming wrong. My guess is that the problem is in one of the class members that you didn't post.

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;

}
RS Conley
+3  A: 

The problem you have is that since ShallowCopy() is a member of KitItem, MemberwiseClone() is just copying the KitItem fields and returning a KitItem even if the original object is a PackageKitItem.

I think what you have to do in this circumstance add to KitItem:

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

and in PackageKitItem:

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

Thus you will get the proper MemberwiseClone() call done depending on the object you are trying to ShallowCopy().

If you wanted to go further, you could define a ShallowCopy() in Product (returning a Product) and then have overridden versions in KitItem and PackageKitItem each returning their respective shallow copy.

TAG