66 lines
2.1 KiB
C#
66 lines
2.1 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace Prefab.Base;
|
|
|
|
/// <summary>
|
|
/// Creates JSON converters that serialize Prefab enums using their logical names.
|
|
/// </summary>
|
|
public sealed class PrefabEnumJsonConverterFactory : JsonConverterFactory
|
|
{
|
|
/// <inheritdoc />
|
|
public override bool CanConvert(Type typeToConvert)
|
|
{
|
|
if (!typeToConvert.IsClass)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var baseType = typeToConvert;
|
|
while (baseType is not null)
|
|
{
|
|
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(PrefabEnum<>))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
baseType = baseType.BaseType;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
|
|
{
|
|
var converterType = typeof(PrefabEnumJsonConverter<>).MakeGenericType(typeToConvert);
|
|
return (JsonConverter)Activator.CreateInstance(converterType)!;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converter used for concrete Prefab enum types.
|
|
/// </summary>
|
|
private sealed class PrefabEnumJsonConverter<TEnum> : JsonConverter<TEnum> where TEnum : PrefabEnum<TEnum>
|
|
{
|
|
/// <inheritdoc />
|
|
public override TEnum? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
|
{
|
|
if (reader.TokenType == JsonTokenType.String)
|
|
{
|
|
var name = reader.GetString() ?? string.Empty;
|
|
return PrefabEnum<TEnum>.FromName(name);
|
|
}
|
|
|
|
if (reader.TokenType == JsonTokenType.Number && reader.TryGetInt32(out var value))
|
|
{
|
|
return PrefabEnum<TEnum>.FromValue(value);
|
|
}
|
|
|
|
throw new JsonException($"Unexpected token {reader.TokenType} when parsing {typeof(TEnum).Name}.");
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) => writer.WriteStringValue(value.Name);
|
|
}
|
|
}
|