static public void StorePropertiesAndFields(DynamicTypeContainer container, object obj, bool allProperties = false)
            {
                var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public;

                foreach (System.Reflection.PropertyInfo prop in obj.GetType().GetProperties(bindingFlags))
                {
                    if (allProperties || Attribute.IsDefined(prop, typeof(DynamicTypeProperty)))
                    {
                        var  value       = prop.GetValue(obj);
                        bool reflectType = value == null ? false : prop.PropertyType != value.GetType();
                        container.SetAttribute(prop.Name, DynamicType.CreateDynamicType(value, allProperties, reflectType));
                    }
                }

                foreach (System.Reflection.FieldInfo field in obj.GetType().GetFields(bindingFlags))
                {
                    if (allProperties || Attribute.IsDefined(field, typeof(DynamicTypeProperty)))
                    {
                        var  value       = field.GetValue(obj);
                        bool reflectType = value == null ? false : field.FieldType != value.GetType();
                        container.SetAttribute(field.Name, DynamicType.CreateDynamicType(value, allProperties, reflectType));
                    }
                }
            }
            public static DynamicType CreateDynamicType(object obj, bool allProperties = false, bool addReflectedType = false)
            {
                if (obj == null)
                {
                    return(new DynamicType());
                }

                System.Type t = obj.GetType();

                if (obj is DynamicType)
                {
                    return(obj as DynamicType);
                }

                if (obj is DynamicTypeContainer)
                {
                    return((DynamicType)(obj as DynamicTypeContainer));
                }

                if (obj is DynamicTypeArray)
                {
                    return((DynamicType)(obj as DynamicTypeArray));
                }

                if (t == typeof(string))
                {
                    return(new DynamicType((string)obj));
                }

                if (t == typeof(Int64))
                {
                    return(new DynamicTypeInt64((Int64)obj));
                }

                if (t == typeof(UInt64))
                {
                    return(new DynamicTypeInt64((UInt64)obj));
                }

                if (t == typeof(Vec2))
                {
                    return(new DynamicType((Vec2)obj));
                }

                if (t == typeof(Vec3))
                {
                    return(new DynamicType((Vec3)obj));
                }

                if (t == typeof(Vec4))
                {
                    return(new DynamicType((Vec4)obj));
                }

                if (t == typeof(Guid))
                {
                    return(new DynamicType((Guid)obj));
                }

                if (t == typeof(Reference))
                {
                    return(new DynamicType((Reference)obj));
                }

                if (t == typeof(System.Type))
                {
                    return(new DynamicType(t.AssemblyQualifiedName));
                }

                if (t.IsEnum)
                {
                    if (Marshal.SizeOf(Enum.GetUnderlyingType(obj.GetType())) <= sizeof(UInt32))
                    {
                        return(new DynamicType((UInt32)Convert.ChangeType(obj, typeof(UInt32))));
                    }
                    else
                    {
                        return(new DynamicType((UInt64)Convert.ChangeType(obj, typeof(UInt64))));
                    }
                }


                if (t.IsValueType && !t.IsPrimitive)     // Struct
                {
                    DynamicTypeContainer cont = new DynamicTypeContainer();
                    DynamicTypeContainer.StorePropertiesAndFields(cont, obj, allProperties);

                    if (addReflectedType)
                    {
                        cont.SetAttribute(TYPE_REFLECT, t.AssemblyQualifiedName);
                    }

                    return(cont);
                }

                if (obj is System.Collections.IDictionary)
                {
                    var dic = obj as System.Collections.IDictionary;
                    if (t.GenericTypeArguments[0] == typeof(string))
                    {
                        DynamicTypeContainer cont = new DynamicTypeContainer();

                        var keys = dic.Keys;
                        var vals = dic.Values;

                        foreach (string key in keys)
                        {
                            cont.SetAttribute(key, CreateDynamicType(dic[key], allProperties, addReflectedType));
                        }

                        return(cont);
                    }
                }

                if (obj is System.Collections.IEnumerable)
                {
                    System.Type elemType = obj.GetType().GetElementType();

                    if (elemType == null && obj.GetType().IsGenericType)
                    {
                        elemType = obj.GetType().GenericTypeArguments[0];
                    }

                    DynamicTypeArray array = new DynamicTypeArray();
                    DynamicTypeArray.StoreEnumerable(array, (System.Collections.IEnumerable)obj, allProperties, elemType);

                    return(array);
                }

                if (t.IsClass)
                {
                    DynamicTypeContainer cont = new DynamicTypeContainer();
                    DynamicTypeContainer.StorePropertiesAndFields(cont, obj, allProperties);

                    if (addReflectedType)
                    {
                        cont.SetAttribute(TYPE_REFLECT, t.AssemblyQualifiedName);
                    }

                    return(cont);
                }

                return(new DynamicType((double)Convert.ChangeType(obj, typeof(double))));    // default to double
            }