Use delegates for custom serializers

This commit is contained in:
Simon Lübeß
2024-01-05 14:34:11 +01:00
parent a5e767df01
commit 9da675e4bb
4 changed files with 43 additions and 16 deletions
@@ -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; }
@@ -39,9 +39,10 @@ public class DeserializationObject
private object _instance;
private Dictionary<string, Type> _fullNameToType = new();
private static Dictionary<Type, MethodInfo> _customDeserializers = new();
private delegate object? DeserializeMethod(DeserializationObject container, string fieldName, Type fieldType);
private static Dictionary<Type, DeserializeMethod> _customDeserializers = new();
/// <summary>
/// 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<CustomSerializerAttribute>(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<DeserializeMethod>();
_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<Bar> -> List<Bar>)
// Note: Foo<Bar> 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)
+11 -7
View File
@@ -19,8 +19,10 @@ public class SerializedObject
private Stack<string> _structScope = new();
private string _structScopeName;
private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType);
private static Dictionary<Type, MethodInfo> _customSerializers = new();
private static Dictionary<Type, SerializeMethod> _customSerializers = new();
public UUID Id => _id;
@@ -53,7 +55,7 @@ public class SerializedObject
{
if (type.TryGetCustomAttribute<CustomSerializerAttribute>(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<SerializeMethod>();
_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<Bar> -> List<Bar>)
// Note: Foo<Bar> 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;
}
}