自动注册实体类到EntityFramework Core上下文,并适配ABP及ABP VNext
继上篇文章(EF Core懒人小技巧之拒绝DbSet)之后,最近笔者把这个小功能单独封装成一个扩展方法并开源,欢迎交流和Star~
GitHub: EntityFrameworkCore.Extension.AutoMapping
Nuget:EntityFrameworkCore.Extension.AutoMapping
EntityFrameworkCore.Extension.AutoMapping.Abp
EntityFrameworkCore.Extension.AutoMapping.AbpVNext
如何使用
在DbContext.cs中重写OnModelCreating方法:
using EntityFrameworkCore.Extension;
... //此处省略其它代码
public class XmateDbContext:DbContext
{
... //此处省略其它代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
modelBuilder.AutoMappingEntityTypes(modelAssemblyName);//泛型IEntity为所有实体类的规约类型
base.OnModelCreating(modelBuilder);//这个必须加,否则报错
...//此处省略其它代码
}
}
这样,我们就可以不用写满屏的DbSet了。
但是,在有的第三方框架中可能就会诞生新的问题。。。
比如在ABP或者VNext框架中,用过ABP框架的都应该知道,ABP是通过扫描DbContext中的DbSet来实现将实体类的仓储自动注册到IOC容器中的,下面我们就需要自己动手来实现:
public static class AutoRegisterEntityRepositoryExtensions
{
///
/// 将数据表实体类型对应的仓储注入到IOC容器
///
///
public static void RegisterDbEntityRepositories(this IIocManager iocManager, string modelAssemblyName) where TDbContext : DbContext
{
foreach (var entityType in GetDbEntityType(typeof(IEntity), modelAssemblyName))
{
var keyType = entityType.GetInterfaces().Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEntity)).SelectMany(t => t.GetGenericArguments()).First();
var genericRepositoryType = typeof(IRepository).MakeGenericType(entityType, keyType);
var impType = typeof(EfCoreRepositoryBase).MakeGenericType(typeof(TDbContext), entityType, keyType);
iocManager.RegisterIfNot(genericRepositoryType, impType, lifeStyle: DependencyLifeStyle.Transient);
}
}
///
/// 获取数据表实体类型列表
///
/// 实体定义约束类型
/// 实体类所在dll名称,不包含后缀名(.dll)
///
private static List GetDbEntityType(Type constraintType, string modelAssemblyName)
{
var all = AppDomain.CurrentDomain.GetAssemblies();
var types = all.WhereIf(!modelAssemblyName.IsNullOrWhiteSpace(), a => a.FullName.Contains(modelAssemblyName))
.SelectMany(m => m.GetTypes().Where(t => t.IsClass && !t.IsAbstract && (t.IsImplement(constraintType) || t.IsSubclass(constraintType))).ToList())
.Distinct()
.ToList();
return types.Where(t => !t.GetCustomAttributes().Any()).ToList();
}
}
注:以上代码摘自:AutoRegisterEntityRepositoryExtensions.cs
在ABP VNext中的实现思路也是如此,这里就不贴代码了,感兴趣的可以查阅源代码
在Abp中实现自动注入实体类对应的Repository
using EntityFrameworkCore.Extension.AutoMapping.Abp;
... //此处省略其它代码
public class XmateModule:AbpModule
{
... //此处省略其它代码
//重写Initialize方法
public override void Initialize()
{
... //此处省略其它代码
var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
IocManager.RegisterDbEntityRepositories(modelAssemblyName);
}
}
在Abp VNext中实现自动注入实体类对应的Repository
using EntityFrameworkCore.Extension.AutoMapping.AbpVNext;
... //此处省略其它代码
public class XmateModule:AbpModule
{
... //此处省略其它代码
//重写ConfigureServices方法
public override void ConfigureServices(ServiceConfigurationContext context)
{
... //此处省略其它代码
var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
context.Services.RegisterDbEntityRepositories(modelAssemblyName);
}
}
THE END
二维码