90 lines
2.3 KiB
C#
90 lines
2.3 KiB
C#
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using System.Reflection;
|
||
|
using System.Text.Json;
|
||
|
using System.Text.Json.Serialization;
|
||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||
|
|
||
|
namespace labdb.Models;
|
||
|
|
||
|
public abstract record EntityIdBase
|
||
|
{
|
||
|
public Guid Value { get; protected internal init; } = Guid.NewGuid();
|
||
|
}
|
||
|
|
||
|
public abstract record EntityIdBase<TId> : EntityIdBase
|
||
|
where TId : EntityIdBase<TId>, new()
|
||
|
{
|
||
|
public static TId Parse(string guid)
|
||
|
{
|
||
|
return new TId { Value = Guid.Parse(guid) };
|
||
|
}
|
||
|
|
||
|
public static bool TryParse(string guid, [NotNullWhen(true)] out TId? value)
|
||
|
{
|
||
|
value = null;
|
||
|
|
||
|
if (!Guid.TryParse(guid, out var result))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
value = new TId
|
||
|
{
|
||
|
Value = result
|
||
|
};
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static TId FromGuid(Guid id)
|
||
|
{
|
||
|
return new TId { Value = id };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class EntityIdConverter<TId> : ValueConverter<TId, Guid>
|
||
|
where TId : EntityIdBase, new()
|
||
|
{
|
||
|
public EntityIdConverter()
|
||
|
: base(id => id.Value,
|
||
|
guid => new TId
|
||
|
{
|
||
|
Value = guid,
|
||
|
})
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class EntityIdJsonConverter<TId> : JsonConverter<TId>
|
||
|
where TId : EntityIdBase, new()
|
||
|
{
|
||
|
public override TId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||
|
{
|
||
|
var guid = reader.GetGuid();
|
||
|
return new TId
|
||
|
{
|
||
|
Value = guid,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
public override void Write(Utf8JsonWriter writer, TId value, JsonSerializerOptions options)
|
||
|
{
|
||
|
writer.WriteStringValue(value.Value.ToString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static class EntityIdJsonConverterExtensions
|
||
|
{
|
||
|
public static void AddEntityIdJsonConverterFromAssembly(this JsonSerializerOptions options, Assembly assembly)
|
||
|
{
|
||
|
var types = assembly.GetTypes()
|
||
|
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(EntityIdBase)));
|
||
|
|
||
|
foreach (var type in types)
|
||
|
{
|
||
|
var converterType = typeof(EntityIdJsonConverter<>).MakeGenericType(type);
|
||
|
var converter = (JsonConverter) Activator.CreateInstance(converterType)!;
|
||
|
options.Converters.Add(converter);
|
||
|
}
|
||
|
}
|
||
|
}
|