我想知道是否有人可能知道如何动态应用实体配置。我不想重复让我们说一下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();
}
}
}
答案 0 :(得分:2)
除了按照另一个答案中的建议创建泛型 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
方法重载,这些重载仅因参数类型而不同,因此找到该方法包括所有检查。
答案 1 :(得分:0)
未经测试,但您可以尝试以下操作:
foreach (Type entityType in entityTypes)
{
Type openConfigType = typeof(BaseEntityConfiguration<>);
Type genericConfigType = openConfigType.MakeGenericType(entityType);
builder.ApplyConfiguration(Activator.CreateInstance(genericConfigType));
}