diff --git a/MLEM.Data/Json/JsonConverters.cs b/MLEM.Data/Json/JsonConverters.cs index 47e0543..184d29c 100644 --- a/MLEM.Data/Json/JsonConverters.cs +++ b/MLEM.Data/Json/JsonConverters.cs @@ -12,7 +12,7 @@ namespace MLEM.Data.Json { /// An array of all of the s that are part of MLEM.Data /// public static readonly JsonConverter[] Converters = typeof(JsonConverters).Assembly.GetExportedTypes() - .Where(t => t.IsSubclassOf(typeof(JsonConverter))) + .Where(t => t.IsSubclassOf(typeof(JsonConverter)) && !t.IsGenericType) .Select(t => t.GetConstructor(Type.EmptyTypes).Invoke(null)).Cast().ToArray(); /// diff --git a/MLEM.Data/Json/StaticJsonConverter.cs b/MLEM.Data/Json/StaticJsonConverter.cs new file mode 100644 index 0000000..be0a70a --- /dev/null +++ b/MLEM.Data/Json/StaticJsonConverter.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; + +namespace MLEM.Data.Json { + /// + /// A that doesn't actually serialize the object, but instead serializes the name given to it by the underlying . + /// Optionally, the name of a can be passed to this converter when used in the by passing the arguments for the constructor as . + /// + /// The type of the object to convert + public class StaticJsonConverter : JsonConverter { + + private readonly Dictionary entries; + private readonly Dictionary inverse; + + /// + /// Creates a new static json converter using the given underlying . + /// + /// The dictionary to use + public StaticJsonConverter(Dictionary entries) { + this.entries = entries; + this.inverse = entries.ToDictionary(kv => kv.Value, kv => kv.Key); + } + + /// + /// Creates a new static json converter by finding the underlying from the given type and member name + /// + /// The name of the type that the dictionary is in + /// The name of the dictionary itself + public StaticJsonConverter(string typeName, string memberName) : + this(GetEntries(typeName, memberName)) { + } + + /// + public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) { + if (!this.inverse.TryGetValue(value, out var key)) + throw new InvalidOperationException($"Cannot write {value} that is not a registered entry"); + writer.WriteValue(key); + } + + /// + public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer) { + var val = reader.Value?.ToString(); + if (val == null) + return default; + this.entries.TryGetValue(val, out var ret); + return ret; + } + + private static Dictionary GetEntries(string typeName, string memberName) { + const BindingFlags flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + var type = Type.GetType(typeName) ?? throw new ArgumentException($"Type {typeName} does not exist", nameof(typeName)); + var value = type.GetProperty(memberName, flags)?.GetValue(null) ?? type.GetField(memberName, flags)?.GetValue(null); + if (value == null) + throw new ArgumentException($"There is no property or field value for name {memberName}", nameof(memberName)); + return value as Dictionary ?? throw new InvalidCastException($"{value} is not of expected type {typeof(T)}"); + } + + } +} \ No newline at end of file