65.9K
CodeProject 正在变化。 阅读更多。
Home

EF Core 应用配置实现

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (5投票s)

2018年5月21日

CPOL
viewsIcon

19709

一个 EF Core 的快速伪代码,等同于实体框架中的 modelBuilder.Configurations.AddFromAssembly

引言

在实体框架中,我们可以使用以下方法加载所有“EntityTypeConfiguration”类

modelBuilder.Configurations.AddFromAssembly(assembly)

在 EF-Core 中,此功能不再可用,但我们必须使用接受实体类型作为类型参数的泛型方法单独添加每个配置。

modelBuilder.ApplyConfiguration<EntityType>(<code>config</code>)

要从特定程序集添加所有配置,我们可以创建一个扩展方法来完成与以下相同的任务

public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{

}

首先,我们将获取所有实现 IEntityTypeConfiguration<> 接口的配置,知道该配置是一个非抽象的非嵌套类

var configurations = assembly.DefinedTypes.Where(t => 
                t.ImplementedInterfaces.Any(i => 
                   i.IsGenericType && 
                   i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
                          StringComparison.InvariantCultureIgnoreCase)
                 )&&
                 t.IsClass &&
                 !t.IsAbstract &&
                 !t.IsNested)
                 .ToList();

然后,我们将使用反射来为我们拥有的每个配置调用模型构建器实例的 ApplyConfiguration 方法

foreach (var configuration in configurations) 
{
       var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);

       var applyConfigMethods = typeof(ModelBuilder).GetMethods().Where(m => m.Name.Equals("ApplyConfiguration") && m.IsGenericMethod);
       var applyConfigMethod = applyConfigMethods.Single(m => m.GetParameters().Any(p => p.ParameterType.Name.Equals(typeof(IEntityTypeConfiguration<>).Name)));

       var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType); 
       
       applyConfigGenericMethod.Invoke(modelBuilder, 
                    new object[] { Activator.CreateInstance(configuration) }); 
}

最终代码如下所示

public static void ApplyConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
      var configurations = assembly.DefinedTypes.Where(t => 
           t.ImplementedInterfaces.Any(i => 
              i.IsGenericType && 
              i.Name.Equals(typeof(IEntityTypeConfiguration<>).Name,
                     StringComparison.InvariantCultureIgnoreCase)
            )&&
            t.IsClass &&
            !t.IsAbstract &&
            !t.IsNested)
            .ToList();

      foreach (var configuration in configurations)
      {
           var entityType = configuration.BaseType.GenericTypeArguments.SingleOrDefault(t => t.IsClass);

           var applyConfigMethod = typeof(ModelBuilder).GetMethod("ApplyConfiguration");

           var applyConfigGenericMethod = applyConfigMethod.MakeGenericMethod(entityType);

           applyConfigGenericMethod.Invoke(modelBuilder, 
                   new object[] { Activator.CreateInstance(configuration) });
      }
}​​​​​​

用法

在此示例中,我们将假设配置存在于 DbContext 的相同程序集中,因此我们的代码将如下所示

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
       base.OnModelCreating(modelBuilder);         
       modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
© . All rights reserved.