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); }
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); }
// ------------ 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); }
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); }
// ------------ 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)); }
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); }
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); }
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); }
// ------------ 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); } } }
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); }
public static BinTreeObject Serialize <T>(MetaEnvironment environment, string path, T metaClass) where T : IMetaClass { return(Serialize(environment, Fnv1a.HashLower(path), metaClass)); }
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)); }
private static void AssignMetaProperty(MetaEnvironment environment, object metaClassObject, PropertyInfo propertyInfo, BinTreeProperty treeProperty) { propertyInfo.SetValue(metaClassObject, DeserializeTreeProperty(environment, treeProperty, propertyInfo.PropertyType)); }