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;
|
namespace GlitchyEngine.Serialization;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
|
||||||
public sealed class CustomSerializerAttribute : Attribute
|
public sealed class CustomSerializerAttribute : Attribute
|
||||||
{
|
{
|
||||||
public Type Type { get; private set; }
|
public Type Type { get; private set; }
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ public class DeserializationObject
|
|||||||
|
|
||||||
private Dictionary<string, Type> _fullNameToType = new();
|
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>
|
/// <summary>
|
||||||
/// Gets the type that was originally stored in the container, or null, if the type doesn't exist.
|
/// 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))
|
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,
|
null,
|
||||||
new []{ typeof(DeserializationObject), typeof(string), typeof(Type) }, null);
|
new []{ typeof(DeserializationObject), typeof(string), typeof(Type) }, null);
|
||||||
|
|
||||||
@@ -79,7 +80,9 @@ public class DeserializationObject
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryCustomDeserializer(string fieldName, Type fieldType, out object deserializedValue)
|
private bool TryCustomDeserializer(string fieldName, Type fieldType, out object? deserializedValue)
|
||||||
{
|
{
|
||||||
deserializedValue = NoValueDeserialized;
|
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>)
|
// 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<>
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType.IsGenericType && _customDeserializers.TryGetValue(fieldType.GetGenericTypeDefinition(), out deserializeMethod))
|
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;
|
} return true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ public class SerializedObject
|
|||||||
|
|
||||||
private string _structScopeName;
|
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;
|
public UUID Id => _id;
|
||||||
|
|
||||||
@@ -53,7 +55,7 @@ public class SerializedObject
|
|||||||
{
|
{
|
||||||
if (type.TryGetCustomAttribute<CustomSerializerAttribute>(out var attribute))
|
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,
|
null,
|
||||||
new[] { typeof(SerializedObject), typeof(string), typeof(object), typeof(Type) }, null);
|
new[] { typeof(SerializedObject), typeof(string), typeof(object), typeof(Type) }, null);
|
||||||
|
|
||||||
@@ -63,7 +65,9 @@ public class SerializedObject
|
|||||||
}
|
}
|
||||||
else
|
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>)
|
// 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<>
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldType.IsGenericType && _customSerializers.TryGetValue(fieldType.GetGenericTypeDefinition(), out serializeMethod))
|
if (fieldType.IsGenericType && _customSerializers.TryGetValue(fieldType.GetGenericTypeDefinition(), out serializeMethod))
|
||||||
{
|
{
|
||||||
serializeMethod.Invoke(null, new[] { this, fieldName, fieldValue, fieldType });
|
serializeMethod(this, fieldName, fieldValue, fieldType);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user