Применение конфигураций объектов в цикле foreach - PullRequest
0 голосов
/ 05 июня 2018

Мне было интересно, может ли кто-нибудь иметь представление о том, как динамически применять конфигурацию объекта.Я не хочу повторяться, скажем, builder.ApplyConfiguration (new PersonConfiguration ());для каждой сущности, которая у меня есть / может быть в будущем.

Я пытался использовать следующий код, и для простоты я поместил все в один файл:

namespace WebApplication1.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            var entityTypes = AppDomain.CurrentDomain.GetAssemblies()
                .SelectMany(p => p.GetTypes())
                .Where(p => typeof(IEntity).IsAssignableFrom(p) && p != typeof(IEntity));

            foreach (var entityType in entityTypes)
            {
                // this doesn't work
                //builder.ApplyConfiguration(new BaseEntityConfiguration<entityType>());
            }

            // this works, but I don't want to basically repeat it for each entity individually
            //builder.ApplyConfiguration(new BaseEntityConfiguration<Person>());
            //builder.ApplyConfiguration(new PersonConfiguration());
        }

        public virtual DbSet<Person> People { get; set; }
    }

    public interface IEntity
    {
        int Id { get; set; }
        string RowModifyUser { get; set; }
        DateTime RowModifyDate { get; set; }
        byte[] RowVersion { get; set; }
    }

    public class Person : IEntity
    {
        public int Id { get; set; }
        public string RowModifyUser { get; set; }
        public DateTime RowModifyDate { get; set; }
        public byte[] RowVersion { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public class BaseEntityConfiguration<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : class, IEntity
    {
        public void Configure(EntityTypeBuilder<TEntity> builder)
        {
            builder.HasKey(m => m.Id);
            builder.Property(m => m.RowModifyDate).IsRequired();
            builder.Property(m => m.RowModifyUser).IsRequired();
            builder.Property(m => m.RowVersion).IsRequired().IsConcurrencyToken();
        }
    }

    public class PersonConfiguration : IEntityTypeConfiguration<Person>
    {
        public void Configure(EntityTypeBuilder<Person> builder)
        {
            builder.Property(m => m.FirstName).IsRequired();
            builder.Property(m => m.LastName).IsRequired();
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

В дополнение к созданию универсального BaseEntityConfiguration<TEntity> класса, как предлагается в другом ответе, вам также необходимо вызвать универсальный ModelBuilder.ApplyConfiguration<TEntity>(IEntityTypeConfiguration<TEntity> configuration) метод с помощью отражения.

Примерно так (нужно using System.Reflection;):

// Can be moved to a static readonly field of the class
var applyConfigurationMethodDefinition = typeof(ModelBuilder)
    .GetTypeInfo()
    .DeclaredMethods
    .Single(m => m.Name == "ApplyConfiguration" &&
        m.IsGenericMethodDefinition &&
        m.GetParameters().Length == 1 &&
        m.GetParameters()[0].ParameterType.IsGenericType &&
        m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>));


foreach (var entityType in entityTypes)
{
    var configurationType = typeof(BaseEntityConfiguration<>).MakeGenericType(entityType);
    var configuration = Activator.CreateIntance(configurationType);

    var applyConfigurationMethod = applyConfigurationMethodDefinition.MakeGenericMethod(entityType);
    applyConfigurationMethod.Invoke(builder, new object[] { configuration });
}

Обратите внимание, что в EF Core 2.1 ModelBuilder класс имеет 2 ApplyConfiguration перегрузки метода, которые отличаются только типом параметра, поэтому поискметод включает в себя все проверки.

0 голосов
/ 05 июня 2018

Не проверено, но вы можете попробовать следующее:

foreach (Type entityType in entityTypes)
{
     Type openConfigType = typeof(BaseEntityConfiguration<>);
     Type genericConfigType = openConfigType.MakeGenericType(entityType);
     builder.ApplyConfiguration(Activator.CreateInstance(genericConfigType));           
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...