Cloning Classes i C# (Unity), is there a short hand for these two code snippets?

255 views Asked by At

So I'm working on an equipment system where I have some Item template classes, than i want to clone each time a new item is instantiated for this i have this bit:

public Item(Item clone)
{
    this.name = clone.name;
    this.description = clone.description;
    this.icon = clone.icon;
    this.mesh = clone.mesh;
    this.weight = clone.weight;
    this.price = clone.price;
}

Can this part be write any smarter in a one line format, that I dont have to update each time i add a new parameter?

Next i inherit a bunch of subclass from Item and to clone these i have made a static class:

public static dynamic EquipmentClone(dynamic toClone)
{
    switch (toClone)
    {
        case Item_Armor item: return new Item_Armor(toClone);
        case Item_Weapon item: return new Item_Weapon(toClone);
        case Item_Equipment item: return new Item_Equipment(toClone);
        case Item item: return new Item(toClone);
        default: return null;
    }

}

This way i can just pass an item into the method and it will instantiate and output a clone of the corresponding type. Can this part be made into a one liner? maybe using generics?

1

There are 1 answers

0
rustyBucketBay On

Try this out:

    private object DeepCopy(object obj) {
            if (obj == null)
                return null;
            Type type = obj.GetType();

            if (type.IsValueType || type == typeof(string)) {
                return obj;
            }
            else if (type.IsArray) {
                Type elementType = Type.GetType(
                     type.FullName.Replace("[]", string.Empty));
                var array = obj as Array;
                Array copied = Array.CreateInstance(elementType, array.Length);
                for (int i = 0; i < array.Length; i++) {
                    copied.SetValue(DeepCopy(array.GetValue(i)), i);
                }
                return Convert.ChangeType(copied, obj.GetType());
            }
            else if (type.IsClass) {

                object toret = Activator.CreateInstance(obj.GetType());
                FieldInfo[] fields = type.GetFields(BindingFlags.Public |
                            BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (FieldInfo field in fields) {
                    object fieldValue = field.GetValue(obj);
                    if (fieldValue == null)
                        continue;
                    field.SetValue(toret, DeepCopy(fieldValue));
                }
                return toret;
            }
            else
                throw new ArgumentException("Unknown type");
        }

add at the top:

using System.Reflection;

And cast to the new type the returned object like this for example:

Item_Armor clonedVarName = (Item_Armor)DeepCopy(cloneSourceVarName);

You dont have to copy your class elements field by field as that is handled by the method above. If that does not work here there are some ideas. I got the posted example from there and directly worked for me.