好的,所以我使用的是带有.Net内核的实体框架和代码优先迁移。这本身并不是问题,我只是想知道是否有人找到了更好的方法来做这件事。
目前我有很多像这样的实体类型配置
public class ExampleEntityConfiguration : IEntityTypeConfiguration<ExampleEntity>
{
   public void Configure(EntityTypeBuilder<ExampleEntity> builder)
   {
      builder.Property(p => p.Id).ValueGeneratedNever();
      // more options here
   }
}并在我的dbcontext中注册它们,如下所示
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  base.OnModelCreating(modelBuilder);
  modelBuilder.ApplyConfiguration(new ExampleEntityConfiguration());
  // lot's more configurations here
}有没有人遇到或知道一种注册所有IEntityTypeConfiguration接口的方法?
这看起来像是许多重复的代码,可以通过获取配置列表、循环它们并在上下文中应用来解决。我只是不知道从哪里开始获取存在于特定名称空间中的IEntityTypeConfiguration类的列表。
任何帮助/建议都是很棒的。
发布于 2017-10-30 19:31:53
它可以通过如下的反射来完成:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);    
    // get ApplyConfiguration method with reflection
    var applyGenericMethod = typeof(ModelBuilder).GetMethod("ApplyConfiguration", BindingFlags.Instance | BindingFlags.Public);            
    // replace GetExecutingAssembly with assembly where your configurations are if necessary
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes()
        .Where(c => c.IsClass && !c.IsAbstract && !c.ContainsGenericParameters)) 
    {
        // use type.Namespace to filter by namespace if necessary
        foreach (var iface in type.GetInterfaces()) {
            // if type implements interface IEntityTypeConfiguration<SomeEntity>
            if (iface.IsConstructedGenericType && iface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>)) {
                // make concrete ApplyConfiguration<SomeEntity> method
                var applyConcreteMethod = applyGenericMethod.MakeGenericMethod(iface.GenericTypeArguments[0]);
                // and invoke that with fresh instance of your configuration type
                applyConcreteMethod.Invoke(modelBuilder, new object[] {Activator.CreateInstance(type)});
                break;
            }
        }
    }
}发布于 2018-12-11 17:55:14
使用EF核心2.2+,它变得简单得多:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   Assembly assemblyWithConfigurations = GetType().Assembly; //get whatever assembly you want
   modelBuilder.ApplyConfigurationsFromAssembly(assemblyWithConfigurations);
}发布于 2017-11-13 19:15:26
@Evk kan的出色工作可以进一步封装在一个可重用的扩展方法中:
 public static class ModelBuilderExtensions
{
    public static void ApplyAllConfigurationsFromCurrentAssembly(this ModelBuilder modelBuilder, Assembly assembly, string configNamespace = "")
    {
        var applyGenericMethods = typeof(ModelBuilder).GetMethods( BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
        var applyGenericApplyConfigurationMethods = applyGenericMethods.Where(m => m.IsGenericMethod && m.Name.Equals("ApplyConfiguration", StringComparison.OrdinalIgnoreCase));
        var applyGenericMethod = applyGenericApplyConfigurationMethods.Where(m=>m.GetParameters().FirstOrDefault().ParameterType.Name== "IEntityTypeConfiguration`1").FirstOrDefault();
        var applicableTypes = assembly
            .GetTypes()
            .Where(c => c.IsClass && !c.IsAbstract && !c.ContainsGenericParameters);
        if (!string.IsNullOrEmpty(configNamespace))
        {
            applicableTypes = applicableTypes.Where(c => c.Namespace == configNamespace);
        }
        foreach (var type in applicableTypes)
        {
            foreach (var iface in type.GetInterfaces())
            {
                // if type implements interface IEntityTypeConfiguration<SomeEntity>
                if (iface.IsConstructedGenericType && iface.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))
                {
                    // make concrete ApplyConfiguration<SomeEntity> method
                    var applyConcreteMethod = applyGenericMethod.MakeGenericMethod(iface.GenericTypeArguments[0]);
                    // and invoke that with fresh instance of your configuration type
                    applyConcreteMethod.Invoke(modelBuilder, new object[] { Activator.CreateInstance(type) });
                    Console.WriteLine("applied model " + type.Name);
                    break;
                }
            }
        }
    }
}并且可以这样调用:
public class ApiDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public ApiDbContext(DbContextOptions<ApiDbContext> options) : base(options) { }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyAllConfigurationsFromCurrentAssembly("MyRoot.Api.Entities.Configuration");
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
    }
}https://stackoverflow.com/questions/47013752
复制相似问题