mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Use delegates for custom serializers
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace GlitchyEngine.Extensions;
|
||||
|
||||
public static class MethodInfoExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Delegate"/> of this <see cref="MethodInfo"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the Delegate.</typeparam>
|
||||
/// <param name="info">The method info.</param>
|
||||
/// <returns>The delegate.</returns>
|
||||
public static T GetDelegate<T>(this MethodInfo info) where T : Delegate
|
||||
{
|
||||
return (T)Delegate.CreateDelegate(typeof(T), info);
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
@@ -40,8 +40,9 @@ public class DeserializationObject
|
||||
|
||||
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)
|
||||
|
||||
@@ -20,7 +20,9 @@ public class SerializedObject
|
||||
|
||||
private string _structScopeName;
|
||||
|
||||
private static Dictionary<Type, MethodInfo> _customSerializers = new();
|
||||
private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user