/// <summary>
        /// Convert the supplied object value into a serialised string format that can be re-created as needed
        /// </summary>
        /// <param name="obj">The object that is to be serialised</param>
        /// <param name="type">The type of object that is being serialised</param>
        /// <returns>Returns a string containing the serialised format of the supplied object</returns>
        public static string Serialise(object obj, Type type)
        {
            //Check that this object can be processed
            if (!CanProcess(type))
            {
                throw new ArgumentException(string.Format("Unable to serialise an object of type '{0}'", type));
            }

            //If this is a collection of objects, process individually
            if (ILIST.IsAssignableFrom(type))
            {
                //Get the object as a list
                IList collection = obj as IList;

                //Create a container for the different values
                SerialCollectionContainer container = new SerialCollectionContainer {
                    vals = new string[collection != null ? collection.Count : 0]
                };

                //Ensure that there are values to process
                if (collection != null)
                {
                    //Get the type of the contained object
                    Type genericType = null;

                    //Check if this object is a list
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == LIST)
                    {
                        //This type needs to have one generic parameter
                        if (type.GetGenericArguments().Length != 1)
                        {
                            throw new ArgumentException(string.Format("Supplied type '{0}' can't be parsed. Type is list but can't determine generic parameter", type));
                        }

                        //Use the generic argument type as the value
                        genericType = type.GetGenericArguments()[0];
                    }

                    //If its an array
                    else if (type.IsArray)
                    {
                        genericType = type.GetElementType();
                    }

                    //Can't use this
                    else
                    {
                        throw new ArgumentException(string.Format("Unable to serialise an object of type '{0}'", type));
                    }

                    //Serialise the individual values
                    for (int i = 0; i < collection.Count; i++)
                    {
                        container.vals[i] = SerialiseValue(collection[i], genericType);
                    }
                }

                //Return the serialised object values
                return(JsonUtility.ToJson(container));
            }

            //Otherwise, general handling
            return(SerialiseValue(obj, type));
        }
        /// <summary>
        /// Parse the supplied text to an object of the specified type
        /// </summary>
        /// <param name="serial">The serialised data that is to be parsed to re-create the object definition</param>
        /// <param name="type">The type of the object that is to be returned by this operation</param>
        /// <returns>Returns a generic object of the specified type</returns>
        public static object Parse(string serial, Type type)
        {
            //Check that this object can be processed
            if (!CanProcess(type))
            {
                throw new ArgumentException(string.Format("Unable to parse an object of type '{0}'", type));
            }

            //If the type is a List
            if (ILIST.IsAssignableFrom(type))
            {
                //Store a reference to the object being returned
                IList list = null;

                //Parse the serial data as a container
                SerialCollectionContainer container = JsonUtility.FromJson <SerialCollectionContainer>(serial);

                //Check if this is a List
                if (type.IsGenericType && type.GetGenericTypeDefinition() == LIST)
                {
                    //Create a new list object from the type
                    list = (IList)Activator.CreateInstance(type, new object[] { container.vals.Length });

                    //This type needs to have one generic parameter
                    if (type.GetGenericArguments().Length != 1)
                    {
                        throw new ArgumentException(string.Format("Supplied type '{0}' can't be parsed. Type is list but can't determine generic parameter", type));
                    }

                    //Use the generic argument type as the value
                    Type genericType = type.GetGenericArguments()[0];

                    //Add objects to the list as they are parsed
                    for (int i = 0; i < container.vals.Length; i++)
                    {
                        list.Add(ParseValue(container.vals[i], genericType));
                    }
                }

                //If the object is an array
                else if (type.IsArray)
                {
                    //Grab the underlying type of the array
                    Type genericType = type.GetElementType();

                    //Create a new array that can hold the returned values
                    list = Array.CreateInstance(genericType, container.vals.Length);

                    //Parse the objects back out as required
                    for (int i = 0; i < container.vals.Length; i++)
                    {
                        list[i] = ParseValue(container.vals[i], genericType);
                    }
                }

                //Return the created instance
                return(list);
            }

            //Otherwise, use basic processing
            return(ParseValue(serial, type));
        }
        /// <summary>
        /// Parse the supplied text to an object of the specified type
        /// </summary>
        /// <param name="serial">The serialised data that is to be parsed to re-create the object definition</param>
        /// <param name="type">The type of the object that is to be returned by this operation</param>
        /// <returns>Returns a generic object of the specified type</returns>
        private static object ParseValue(string serial, Type type)
        {
            //Check if the object is one of the default types
            if (type == SBYTE)
            {
                sbyte val;    sbyte.TryParse(serial, out val);    return(val);
            }
            if (type == SHORT)
            {
                short val;    short.TryParse(serial, out val);    return(val);
            }
            if (type == INT)
            {
                int val;      int.TryParse(serial, out val);      return(val);
            }
            if (type == LONG)
            {
                long val;     long.TryParse(serial, out val);     return(val);
            }
            if (type == BYTE)
            {
                byte val;     byte.TryParse(serial, out val);     return(val);
            }
            if (type == USHORT)
            {
                ushort val;   ushort.TryParse(serial, out val);   return(val);
            }
            if (type == UINT)
            {
                uint val;     uint.TryParse(serial, out val);     return(val);
            }
            if (type == ULONG)
            {
                ulong val;    ulong.TryParse(serial, out val);    return(val);
            }
            if (type == FLOAT)
            {
                float val;    float.TryParse(serial, out val);    return(val);
            }
            if (type == DOUBLE)
            {
                double val;   double.TryParse(serial, out val);   return(val);
            }
            if (type == DECIMAL)
            {
                decimal val;  decimal.TryParse(serial, out val);  return(val);
            }
            if (type == BOOL)
            {
                bool val;     bool.TryParse(serial, out val);     return(val);
            }
            if (type == STRING)
            {
                return(serial);
            }
            if (type == CHAR)
            {
                short val;    short.TryParse(serial, out val);    return((char)val);
            }

            //If this is a Unity Engine object, deserialise the usual way
            if (UOBJ.IsAssignableFrom(type))
            {
                //Deserialise the object container
                SerialUnityObjectContainer objectContainer = JsonUtility.FromJson <SerialUnityObjectContainer>(serial);

                //Return the object reference value
                return(objectContainer.obj);
            }

            //If the object is an enumeration
            if (ENUM.IsAssignableFrom(type))
            {
                //Deserialise a container object
                SerialCollectionContainer container = JsonUtility.FromJson <SerialCollectionContainer>(serial);

                //There should be two values in the container
                if (container.vals.Length != 2)
                {
                    throw new ArgumentException("Serialised enumeration data has two values for processing. Received " + container.vals.Length);
                }

                //Determine the type that is being used
                Type enumType = Type.GetType(container.vals[0]);

                //Get the integral value to use
                long val = Convert.ToInt64(container.vals[1]);

                //Return the final value converted to the enumeration
                return(Enum.ToObject(enumType, val));
            }

            //At this point, use JsonUtility to manage other types
            return(JsonUtility.FromJson(serial, type));
        }