У меня есть репозиторий здесь: https://github.com/sebastianwhiffen/Generically -Typed-Entities-with-EF-Core, демонстрирующий использование универсальных шаблонов в качестве своего рода «дискриминатора» для сопоставления таблиц. Но НЕ вложенные дженерики.
В Program.cs продукт того, что я написал, создает краткий API:
Код: Выделить всё
// gets all clients
repo.Get().OfType()
.ToList().ForEach(x => Console.WriteLine(x.GetDisplayName()));
// gets individuals from the DB
repo.Get().OfType()
.ToList().ForEach(x => Console.WriteLine(x.GetDisplayName()));
// gets companies
repo.Get().OfType()
.ToList().ForEach(x => Console.WriteLine(x.GetDisplayName()));
// you get the idea
repo.Get().OfType()
.ToList().ForEach(x => Console.WriteLine(x.GetDisplayName()));
Код: Выделить всё
public class MyDB : DbContext
{
public MyDB(DbContextOptions options) : base(options) { }
public DbSet Clients { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.MapClientTypes();
}
}
Код: Выделить всё
public static class ModelBuilderHelper
{
public static void MapClientTypes(this ModelBuilder modelBuilder)
{
var clientTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && typeof(IClient).IsAssignableFrom(t))
.ToList();
foreach (var clientType in clientTypes)
{
var genericClientType = typeof(Client).MakeGenericType(clientType);
var entityTypeBuilder = modelBuilder.Entity(genericClientType);
var dataProperty = genericClientType.GetProperty("Data");
entityTypeBuilder.OwnsOne(dataProperty.PropertyType, dataProperty.Name);
}
}
}
Код: Выделить всё
repo.Get().OfType()
.ToList().ForEach(x => Console.WriteLine(x.GetIdentifier()));
Вот как я пытаюсь расширить демо-версию. Я пытаюсь добавить еще один уровень обобщений над типом Client под названием Entity.
Клиент выглядит вот так
Код: Выделить всё
public class Client : Client where T : Entity, IClient, IEntity, new()
{
public T Data { get; set; }
public Client()
{
Data = Activator.CreateInstance();
}
public override string GetIdentifier() => Data.GetIdentifier();
}
public abstract class Client : Entity;
Код: Выделить всё
public class Entity : Entity where T : Entity, IEntity, new()
{
public T Data {get; set;}
public Entity()
{
Data = Activator.CreateInstance();
}
public override string GetIdentifier() => Data.GetIdentifier();
}
public abstract class Entity
{
public int ID { get; set; }
public abstract string GetIdentifier();
}
Экземпляр типа сущности «Сущность» нельзя отслеживать как тип сущности «Client.Data#SoleTrader», поскольку эти два типа не находятся в одной и той же иерархии.
И это из моих общих репозиториев _context.Add(entity).
Я опубликовал здесь код, выдающий эту ошибку: https://github.com/sebastianwhiffen/Complex-Generic-EF -Сущности, если вы хотите посмотреть больше контекста.
Но в сумме. Я хочу иметь возможность создавать иерархию вложенных универсальных объектов, начиная с Entity, и (теоретически) иметь возможность продолжать это вложение так долго, как захочу.
Есть идеи? любые другие решения, которые предоставляют мне этот краткий общий синтаксис репо, избегая при этом серьезных болей в запястьях при записи
Код: Выделить всё
public class SoleTraderClient : Client { }
public class SoleTraderEntity : Entity { }
etc...
Подробнее здесь: https://stackoverflow.com/questions/792 ... th-ef-core