Beispiel #1
0
        public static BinTreeObject Serialize <T>(MetaEnvironment environment, uint pathHash, T metaClass)
            where T : IMetaClass
        {
            Type metaClassType = metaClass.GetType();
            MetaClassAttribute metaClassAttribute = metaClassType.GetCustomAttribute(typeof(MetaClassAttribute)) as MetaClassAttribute;

            if (metaClassAttribute is null)
            {
                throw new InvalidOperationException("The provided MetaClass does not have a MetaClass Attribute");
            }

            // Create Tree Properties for meta properties
            List <BinTreeProperty> properties = new();

            foreach (PropertyInfo propertyInfo in metaClassType.GetProperties())
            {
                BinTreeProperty treeProperty = ConvertPropertyToTreeProperty(environment, metaClass, propertyInfo);

                if (treeProperty is not null)
                {
                    properties.Add(treeProperty);
                }
            }

            BinTreeObject treeObject = new BinTreeObject(metaClassAttribute.NameHash, pathHash, properties);

            return(treeObject);
        }
Beispiel #2
0
        public static T Deserialize <T>(MetaEnvironment environment, BinTreeObject treeObject)
            where T : IMetaClass
        {
            Type metaClassType = typeof(T);
            MetaClassAttribute metaClassAttribute = metaClassType.GetCustomAttribute(typeof(MetaClassAttribute)) as MetaClassAttribute;

            // Verify attribute
            if (metaClassAttribute is null)
            {
                throw new InvalidOperationException("The provided MetaClass does not have a MetaClass Attribute");
            }
            if (metaClassAttribute.NameHash != treeObject.MetaClassHash)
            {
                throw new InvalidOperationException("Meta Class name does not match class name of treeObject");
            }

            // Create an instance of T and get its runtime type
            T    metaClassObject     = Activator.CreateInstance <T>();
            Type metaClassObjectType = metaClassObject.GetType();

            // Assign values to the object properties
            AssignMetaClassProperties(environment, metaClassObject, metaClassObjectType, treeObject.Properties);

            // Registered the object in the environment for link resolving
            environment.RegisterObject(treeObject.PathHash, metaClassObject);

            return(metaClassObject);
        }
Beispiel #3
0
        // ------------ PROPERTY DESERIALIZATION ------------ \\
        private static object DeserializeTreeProperty(MetaEnvironment environment, BinTreeProperty treeProperty, Type propertyType = null)
        {
            BinPropertyType treePropertyType = treeProperty.Type;

            if (IsPrimitivePropertyType(treePropertyType))
            {
                return(FetchPrimitivePropertyValue(treeProperty));
            }
            else if (treePropertyType == BinPropertyType.Container || treePropertyType == BinPropertyType.UnorderedContainer)
            {
                return(DeserializeContainer(environment, propertyType, treeProperty as BinTreeContainer));
            }
            else if (treePropertyType == BinPropertyType.Structure)
            {
                return(DeserializeStructure(environment, treeProperty as BinTreeStructure));
            }
            else if (treePropertyType == BinPropertyType.Embedded)
            {
                return(DeserializeEmbedded(environment, treeProperty as BinTreeEmbedded));
            }
            else if (treePropertyType == BinPropertyType.Map)
            {
                return(DeserializeMap(environment, propertyType, treeProperty as BinTreeMap));
            }
            else if (treePropertyType == BinPropertyType.Optional)
            {
                return(DeserializeOptional(environment, propertyType, treeProperty as BinTreeOptional));
            }

            return(null);
        }
Beispiel #4
0
        private static object DeserializeOptional(MetaEnvironment environment, Type propertyType, BinTreeOptional optional)
        {
            bool   isSome         = optional.Value is not null;
            object value          = isSome ? DeserializeTreeProperty(environment, optional.Value) : GetTypeDefault(propertyType);
            object optionalObject = Activator.CreateInstance(propertyType, new[] { value, isSome });

            return(optionalObject);
        }
Beispiel #5
0
        // ------------ SERIALIZATION ------------ \\
        private static BinTreeProperty ConvertPropertyToTreeProperty(MetaEnvironment environment, object metaClassObject, PropertyInfo propertyInfo)
        {
            MetaPropertyAttribute metaPropertyAttribute = propertyInfo.GetCustomAttribute(typeof(MetaPropertyAttribute)) as MetaPropertyAttribute;

            if (metaPropertyAttribute is null)
            {
                throw new InvalidOperationException("The specified property does not have a MetaProperty Attribute");
            }

            object value = propertyInfo.GetValue(metaClassObject);

            return(ConvertObjectToProperty(environment, metaPropertyAttribute.NameHash, value, propertyInfo.PropertyType));
        }
Beispiel #6
0
        private static object DeserializeContainer(MetaEnvironment environment, Type propertyType, BinTreeContainer container)
        {
            object     containerList     = Activator.CreateInstance(propertyType);
            Type       containerListType = containerList.GetType();
            MethodInfo addMethod         = containerListType.GetMethod("Add");

            foreach (BinTreeProperty containerItem in container.Properties)
            {
                addMethod.Invoke(containerList, new[] { DeserializeTreeProperty(environment, containerItem) });
            }

            return(containerList);
        }
Beispiel #7
0
        private static object DeserializeStructure(MetaEnvironment environment, BinTreeStructure structure)
        {
            Type metaClassType = environment.FindMetaClass(structure.MetaClassHash);

            if (metaClassType is null)
            {
                return(null);                       // Couldn't deserialize structure
            }
            object metaClassObject = Activator.CreateInstance(metaClassType);

            AssignMetaClassProperties(environment, metaClassObject, metaClassObject.GetType(), structure.Properties);

            return(metaClassObject);
        }
Beispiel #8
0
        private static object DeserializeEmbedded(MetaEnvironment environment, BinTreeEmbedded embedded)
        {
            Type metaClassType = environment.FindMetaClass(embedded.MetaClassHash);

            if (metaClassType is null)
            {
                return(null);                       // Couldn't deserialize structure
            }
            Type embeddedWrapperType = typeof(MetaEmbedded <>).MakeGenericType(metaClassType);

            object metaClassObject = Activator.CreateInstance(metaClassType);

            AssignMetaClassProperties(environment, metaClassObject, metaClassObject.GetType(), embedded.Properties);

            object embeddedWrapperObject = Activator.CreateInstance(embeddedWrapperType, new[] { metaClassObject });

            return(embeddedWrapperObject);
        }
Beispiel #9
0
        // ------------ DESERIALIZATION ASSIGNMENT ------------ \\
        private static void AssignMetaClassProperties(MetaEnvironment environment, object metaClassObject, Type metaClassType, ICollection <BinTreeProperty> treeProperties)
        {
            PropertyInfo[] properties = metaClassType.GetProperties();

            foreach (PropertyInfo propertyInfo in properties)
            {
                MetaPropertyAttribute metaPropertyAttribute = propertyInfo.GetCustomAttribute(typeof(MetaPropertyAttribute)) as MetaPropertyAttribute;

                // Ignore non-meta properties
                if (metaPropertyAttribute is null)
                {
                    continue;
                }

                // Find matching tree property
                BinTreeProperty treeProperty = treeProperties.FirstOrDefault(x => x.NameHash == metaPropertyAttribute.NameHash);
                if (treeProperty is not null) // Ignore missing properties
                {
                    // Assign values to properties
                    AssignMetaProperty(environment, metaClassObject, propertyInfo, treeProperty);
                }
            }
        }
Beispiel #10
0
        private static object DeserializeMap(MetaEnvironment environment, Type propertyType, BinTreeMap map)
        {
            // Invalid key type
            if (IsValidMapKey(map.KeyType) is false)
            {
                return(null);
            }

            object     mapDictionary     = Activator.CreateInstance(propertyType);
            Type       mapDictionaryType = mapDictionary.GetType();
            MethodInfo addMethod         = mapDictionaryType.GetMethod("Add");

            foreach (var propertyPair in map.Map)
            {
                // Key types can only be primitive so we can fetch their value easily
                object keyValue   = FetchPrimitivePropertyValue(propertyPair.Key);
                object valueValue = DeserializeTreeProperty(environment, propertyPair.Value);

                addMethod.Invoke(mapDictionary, new[] { keyValue, valueValue });
            }

            return(mapDictionary);
        }
Beispiel #11
0
 public static BinTreeObject Serialize <T>(MetaEnvironment environment, string path, T metaClass)
     where T : IMetaClass
 {
     return(Serialize(environment, Fnv1a.HashLower(path), metaClass));
 }
Beispiel #12
0
        private static BinTreeProperty ConvertObjectToProperty(MetaEnvironment environment, uint nameHash, object value, Type valueType)
        {
            // Handle primitives
            if (value is null)
            {
                return(null);
            }
            else if (valueType == typeof(bool?))
            {
                return(new BinTreeBool(null, nameHash, (bool)value));
            }
            else if (valueType == typeof(sbyte?))
            {
                return(new BinTreeSByte(null, nameHash, (sbyte)value));
            }
            else if (valueType == typeof(byte?))
            {
                return(new BinTreeByte(null, nameHash, (byte)value));
            }
            else if (valueType == typeof(short?))
            {
                return(new BinTreeInt16(null, nameHash, (short)value));
            }
            else if (valueType == typeof(ushort?))
            {
                return(new BinTreeUInt16(null, nameHash, (ushort)value));
            }
            else if (valueType == typeof(int?))
            {
                return(new BinTreeInt32(null, nameHash, (int)value));
            }
            else if (valueType == typeof(uint?))
            {
                return(new BinTreeUInt32(null, nameHash, (uint)value));
            }
            else if (valueType == typeof(long?))
            {
                return(new BinTreeInt64(null, nameHash, (long)value));
            }
            else if (valueType == typeof(ulong?))
            {
                return(new BinTreeUInt64(null, nameHash, (ulong)value));
            }
            else if (valueType == typeof(float?))
            {
                return(new BinTreeFloat(null, nameHash, (float)value));
            }
            else if (valueType == typeof(Vector2?))
            {
                return(new BinTreeVector2(null, nameHash, (Vector2)value));
            }
            else if (valueType == typeof(Vector3?))
            {
                return(new BinTreeVector3(null, nameHash, (Vector3)value));
            }
            else if (valueType == typeof(Vector4?))
            {
                return(new BinTreeVector4(null, nameHash, (Vector4)value));
            }
            else if (valueType == typeof(Matrix4x4?))
            {
                return(new BinTreeMatrix44(null, nameHash, (Matrix4x4)value));
            }
            else if (valueType == typeof(Color?))
            {
                return(new BinTreeColor(null, nameHash, (Color)value));
            }
            else if (valueType == typeof(string))
            {
                return(new BinTreeString(null, nameHash, (string)value));
            }
            else if (valueType == typeof(MetaHash?))
            {
                return(new BinTreeHash(null, nameHash, (MetaHash)value));
            }
            else if (valueType == typeof(MetaWadEntryLink?))
            {
                return(new BinTreeWadEntryLink(null, nameHash, (MetaWadEntryLink)value));
            }
            else if (valueType == typeof(MetaObjectLink?))
            {
                return(new BinTreeObjectLink(null, nameHash, (MetaObjectLink)value));
            }
            else if (valueType == typeof(MetaBitBool?))
            {
                return(new BinTreeBitBool(null, nameHash, (MetaBitBool)value));
            }
            else
            {
                // Handle complex types
                if (valueType.IsGenericType)
                {
                    Type genericTypeDefinition = valueType.GetGenericTypeDefinition();

                    if (genericTypeDefinition == typeof(Dictionary <,>))
                    {
                        return(CreateMapProperty(environment, nameHash, valueType.GenericTypeArguments[0], valueType.GenericTypeArguments[1], value as IDictionary));
                    }
                    else if (genericTypeDefinition == typeof(MetaUnorderedContainer <>))
                    {
                        return(CreateUnorderedContainerProperty(environment, nameHash, valueType.GenericTypeArguments[0], value as IEnumerable));
                    }
                    else if (genericTypeDefinition == typeof(MetaContainer <>))
                    {
                        return(CreateContainerProperty(environment, nameHash, valueType.GenericTypeArguments[0], value as IEnumerable));
                    }
                    else if (genericTypeDefinition == typeof(MetaOptional <>))
                    {
                        return(CreateOptionalProperty(environment, nameHash, valueType.GenericTypeArguments[0], value as IMetaOptional));
                    }
                    else if (genericTypeDefinition == typeof(MetaEmbedded <>))
                    {
                        return(CreateEmbeddedProperty(environment, nameHash, valueType.GenericTypeArguments[0], value as IMetaEmbedded));
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    // Check if we're dealing with a Structure type
                    if (valueType.IsValueType is false && valueType.GetInterface(nameof(IMetaClass)) is not null)
                    {
                        return(CreateStructureProperty(environment, value, nameHash));
                    }
Beispiel #13
0
 private static void AssignMetaProperty(MetaEnvironment environment, object metaClassObject, PropertyInfo propertyInfo, BinTreeProperty treeProperty)
 {
     propertyInfo.SetValue(metaClassObject, DeserializeTreeProperty(environment, treeProperty, propertyInfo.PropertyType));
 }