diff --git a/ScriptCore/Extensions/MethodInfoExtension.cs b/ScriptCore/Extensions/MethodInfoExtension.cs new file mode 100644 index 0000000..ad09f59 --- /dev/null +++ b/ScriptCore/Extensions/MethodInfoExtension.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace GlitchyEngine.Extensions; + +public static class MethodInfoExtension +{ + /// + /// Gets the of this . + /// + /// The type of the Delegate. + /// The method info. + /// The delegate. + public static T GetDelegate(this MethodInfo info) where T : Delegate + { + return (T)Delegate.CreateDelegate(typeof(T), info); + } +} diff --git a/ScriptCore/Serialization/CustomSerializerAttribute.cs b/ScriptCore/Serialization/CustomSerializerAttribute.cs index ad932d1..2240db1 100644 --- a/ScriptCore/Serialization/CustomSerializerAttribute.cs +++ b/ScriptCore/Serialization/CustomSerializerAttribute.cs @@ -4,7 +4,7 @@ using System.Text; namespace GlitchyEngine.Serialization; -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] public sealed class CustomSerializerAttribute : Attribute { public Type Type { get; private set; } diff --git a/ScriptCore/Serialization/DeserializationObject.cs b/ScriptCore/Serialization/DeserializationObject.cs index c13b350..552d20b 100644 --- a/ScriptCore/Serialization/DeserializationObject.cs +++ b/ScriptCore/Serialization/DeserializationObject.cs @@ -39,9 +39,10 @@ public class DeserializationObject private object _instance; private Dictionary _fullNameToType = new(); - - private static Dictionary _customDeserializers = new(); + private delegate object? DeserializeMethod(DeserializationObject container, string fieldName, Type fieldType); + + private static Dictionary _customDeserializers = new(); /// /// Gets the type that was originally stored in the container, or null, if the type doesn't exist. @@ -69,7 +70,7 @@ public class DeserializationObject { if (type.TryGetCustomAttribute(out var attribute)) { - MethodInfo deserializeMethod = type.GetMethod("Deserialize", BindingFlags.Static | BindingFlags.Public, + MethodInfo? deserializeMethod = type.GetMethod("Deserialize", BindingFlags.Static | BindingFlags.Public, null, new []{ typeof(DeserializationObject), typeof(string), typeof(Type) }, null); @@ -79,7 +80,9 @@ public class DeserializationObject } else { - _customDeserializers.Add(attribute.Type, deserializeMethod); + DeserializeMethod method = deserializeMethod.GetDelegate(); + + _customDeserializers.Add(attribute.Type, method); } } } @@ -264,7 +267,7 @@ public class DeserializationObject return changed; } - private bool TryCustomDeserializer(string fieldName, Type fieldType, out object deserializedValue) + private bool TryCustomDeserializer(string fieldName, Type fieldType, out object? deserializedValue) { deserializedValue = NoValueDeserialized; @@ -272,15 +275,15 @@ public class DeserializationObject { // Try to match the concrete type first (e.g. Foo -> Foo and Foo -> List) // Note: Foo wont match a serializer for Foo<> - if (_customDeserializers.TryGetValue(fieldType, out MethodInfo deserializeMethod)) + if (_customDeserializers.TryGetValue(fieldType, out DeserializeMethod deserializeMethod)) { - deserializedValue = deserializeMethod.Invoke(null, new object[] { this, fieldName, fieldType }); + deserializedValue = deserializeMethod(this, fieldName, fieldType); return true; } if (fieldType.IsGenericType && _customDeserializers.TryGetValue(fieldType.GetGenericTypeDefinition(), out deserializeMethod)) { - deserializedValue = deserializeMethod.Invoke(null, new object[] { this, fieldName, fieldType }); + deserializedValue = deserializeMethod(this, fieldName, fieldType); } return true; } catch (Exception e) diff --git a/ScriptCore/Serialization/SerializedObject.cs b/ScriptCore/Serialization/SerializedObject.cs index 96c39d7..3a390c0 100644 --- a/ScriptCore/Serialization/SerializedObject.cs +++ b/ScriptCore/Serialization/SerializedObject.cs @@ -19,8 +19,10 @@ public class SerializedObject private Stack _structScope = new(); private string _structScopeName; + + private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType); - private static Dictionary _customSerializers = new(); + private static Dictionary _customSerializers = new(); public UUID Id => _id; @@ -53,7 +55,7 @@ public class SerializedObject { if (type.TryGetCustomAttribute(out var attribute)) { - MethodInfo serializeMethod = type.GetMethod("Serialize", BindingFlags.Static | BindingFlags.Public, + MethodInfo? serializeMethod = type.GetMethod("Serialize", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(SerializedObject), typeof(string), typeof(object), typeof(Type) }, null); @@ -63,7 +65,9 @@ public class SerializedObject } else { - _customSerializers.Add(attribute.Type, serializeMethod); + SerializeMethod method = serializeMethod.GetDelegate(); + + _customSerializers.Add(attribute.Type, method); } } } @@ -116,15 +120,15 @@ public class SerializedObject { // Try to match the concrete type first (e.g. Foo -> Foo and Foo -> List) // Note: Foo wont match a serializer for Foo<> - if (_customSerializers.TryGetValue(fieldType, out MethodInfo serializeMethod)) + if (_customSerializers.TryGetValue(fieldType, out SerializeMethod serializeMethod)) { - serializeMethod.Invoke(null, new[] { this, fieldName, fieldValue, fieldType }); + serializeMethod(this, fieldName, fieldValue, fieldType); return true; } - + if (fieldType.IsGenericType && _customSerializers.TryGetValue(fieldType.GetGenericTypeDefinition(), out serializeMethod)) { - serializeMethod.Invoke(null, new[] { this, fieldName, fieldValue, fieldType }); + serializeMethod(this, fieldName, fieldValue, fieldType); return true; } }