Multiplatform Deep Copy in XNA


This week on Game Dev Without a Cause, we’re going deep. Deep copy that is! Okay, you really have to be a programmer to find that all appealing.

You may not need to do it often, but when you do it’s really useful to have an easy deep copying solution on hand. As simple as it is conceptually, it can be surprisingly difficulty to find a general-purpose way to perform deep-copies on arbitrary collections of data. It can be especially difficult with XNA because the Xbox 360 doesn’t have the full set of features available to the Windows version of the framework. Sure, it’s easy enough to write deep copy logic for simple structures, but who wants to be stuck updating Clone() functions or the like every time they add a member to a particular class.

So, recently, I had the dubious pleasure of trying to find a way to implement deep copy functionality in C#. Implementing the ICloneable interface is an option, but it is undefined as to whether or not it should be a deep clone. Also, I would have had to implement all the Clone() functions by-hand and keep them up-to-date. No thanks.

Another solution, that I actually started using for a while, was serialization using BinaryFormatter. This worked pretty well for me although I wasn’t crazy about having to mark up any classes I would deep copy with [Serializable] attributes. Beyond that though, I found out that BinaryFormatter wasn’t implemented on the Xbox 360. So much for that solution.

Finally, I stumbled upon this implementation on CodeProject using reflection to perform general-purpose deep copies. Reflection is definitely not one of the fastest ways to do deep copies, but it works on both Windows and Xbox 360 which was what I was looking for. One caveat to bear in mind is that private members of base classes are not returned when you call GetFields() so, if you want the data of a base class to be copied, it has to be protected or public.

So, if you ever find yourself needing to perform a deep copy in XNA on both Windows and Xbox 360, this code is for you:

        //Deep Copy code by DetoX83 from http://www.codeproject.com/Articles/38270/Deep-copy-of-objects-in-C

        static T DeepCopy<T>(T obj)
        {
            if (obj == null)
                throw new ArgumentNullException("Object cannot be null");
            return (T)Process(obj);
        }

        static object Process(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(Process(array.GetValue(i)), i);
                }
                return Convert.ChangeType(copied, obj.GetType(), null);
            }
            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, Process(fieldValue));
                }
                return toret;
            }
            else
                throw new ArgumentException("Unknown type");
        }
Share this Article:
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Print

One thought on “Multiplatform Deep Copy in XNA

  1. Pingback: Return to the Deep (Copy) | Game Dev Without a Cause

Comments are closed.