using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace labdb.Models; public abstract class EntityBase where TId : EntityIdBase, new() { // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Local - EF Core needs a setter public TId Id { get; private set; } = new(); } public abstract class EntityBaseConfiguration : IEntityTypeConfiguration where TEntity : EntityBase where TId : EntityIdBase, new() { public virtual void Configure(EntityTypeBuilder builder) { builder.HasKey(x => x.Id); ApplyTypedIdConverters(builder); ApplyEnumConverters(builder); } private void ApplyTypedIdConverters(EntityTypeBuilder builder) { foreach (var propertyInfo in typeof(TEntity).GetProperties() .Where(x => x.PropertyType.IsAssignableTo(typeof(EntityIdBase)))) { var idConverterType = typeof(EntityIdConverter<>).MakeGenericType(propertyInfo.PropertyType); var idConverterConstructor = idConverterType.GetConstructor(Array.Empty()); var idConverter = (ValueConverter)idConverterConstructor!.Invoke(Array.Empty()); builder.Property(propertyInfo.Name) .HasConversion(idConverter); } } private void ApplyEnumConverters(EntityTypeBuilder builder) { foreach (var propertyInfo in typeof(TEntity).GetProperties() .Where(x => x.PropertyType.IsEnum)) { var enumConverterType = typeof(EnumConverter<>).MakeGenericType(propertyInfo.PropertyType); var enumConverterConstructor = enumConverterType.GetConstructor(Array.Empty()); var enumConverter = (ValueConverter)enumConverterConstructor!.Invoke(Array.Empty()); builder.Property(propertyInfo.Name) .HasConversion(enumConverter); } } } public class EnumConverter : ValueConverter where TEnum : Enum { public EnumConverter() : base( x => x.ToString(), x => (TEnum)Enum.Parse(typeof(TEnum), x)) { } }