ABP框架使用拦截器动态配置租户过滤器
前言
最近項目要求在ABP框架中根據TenantId是否為空來配置是否禁用租戶過濾器。ABP自身給我我們禁用租戶過濾器的兩種方法官方文檔
https://aspnetboilerplate.com/Pages/Documents/Data-Filters
方法一:使用工作單元
using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant)) {var people2 = _personRepository.GetAllList(); }方法二:全局禁用過濾器
Configuration.UnitOfWork.OverrideFilter(AbpDataFilters.MayHaveTenant, false);但是方法一要修改的地方很多,嫌麻煩;方法二只能全局在Configuration中配置,不能動態改變,也不合適。于是我查閱了APB AOP和攔截技術 ,另外查閱了ABP自身注冊了攔截器——UnitOfWorkRegistrar,會默認為繼承自IRepository或者是IApplicationService的兩種類型添加UnitOfWork特性,于是便可以通過攔截方法去實現動態禁用過濾器。
具體實現
首先在Application 層新建一個TenantInterceptor 繼承IInterceptor接口
public class TenantInterceptor : IInterceptor {public ILogger Logger { get; set; }public TenantInterceptor(){Logger = NullLogger.Instance;}public void Intercept(IInvocation invocation){// 從invocation中拿到當前注冊進來的工作單元,主要用于獲取TenantIdType t = invocation.InvocationTarget.GetType();var unitOfWorkManager = (t.GetProperty("UnitOfWorkManager").GetValue(invocation.InvocationTarget)) as IUnitOfWorkManager;//根據TenantId是否禁用租戶過濾器if (unitOfWorkManager.Current.GetTenantId().HasValue){invocation.Proceed(); // 執行方法體}else {// 禁用租戶// PS:這里不可以使用 using unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant, AbpDataFilters.MustHaveTenant);invocation.Proceed(); // 執行方法體}} }攔截器里的內容很簡單,主要就是根據工作單元獲取TenantId來動態禁用過濾器。因為這里沒有需要返回的東西,也就不用分同步異步去攔截。
接下來就是為所需要禁用租戶過濾器的類注冊攔截器
public static class TenantInterceptorRegistrar {public static void Initialize(IKernel kernel){kernel.ComponentRegistered += Kernel_ComponentRegistered;}private static void Kernel_ComponentRegistered(string key, IHandler handler){var implementationType = handler.ComponentModel.Implementation.GetTypeInfo();// 為實現了接口IRepository接口的所有類注冊攔截器//if (typeof(IRepository).IsAssignableFrom(implementationType))//{// handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(TenantInterceptor)));//}// 為指定類注冊攔截器if (InternalAsyncHelper.DisableFilterTenantTypes.Any(a => a.IsAssignableFrom(implementationType))){handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(TenantInterceptor)));}} }internal static class InternalAsyncHelper {public static Type[] DisableFilterTenantTypes ={typeof(IRepository<Student,Guid>),typeof(IRepository<School,Guid>)}; }在TenantInterceptorRegistrar的Initialize方法中,首先會注入整個ABP系統中唯一的IIocManager,然后就是訂閱唯一的IocContainer這個容器的ComponentRegistered事件,在訂閱事件中首先是獲取當前觸發此事件的類型信息,然后根據需求注冊TenantInterceptor這個攔截器。
這里有一點需要注意,本來想為實現了IApplicationService接口的類注冊攔截器,但是ASP.NET ? Boilerplate使用動態方法攔截的功能有一些限制
如果通過接口調用該方法,則可以將其用于任何公共方法(例如,通過接口使用的Application Services)。
如果直接從類引用(例如ASP.NET ?MVC或Web API控制器)中調用方法,則該方法應為虛擬方法。
一種方法應該是虛擬的,如果它的保護。
也就是如果將服務作為客戶端的Web API控制器公開,那么方法必須是虛方法(virtual) 附上官方Git issues
https://github.com/aspnetboilerplate/aspnetboilerplate/issues/3237
最后一步就是把攔截器在模塊文件中初始化
public class ApplicationCoreModule : AbpModule {public override void PreInitialize(){TenantInterceptorRegistrar.Initialize(IocManager.IocContainer.Kernel);}public override void Initialize(){} }這樣就可以按著自己的需要在DisableFilterTenantTypes ?中配置自己想配置的倉儲了。
轉載是一種動力 分享是一種美德
如果喜歡作者的文章,請關注【麥扣聊技術】訂閱號以便第一時間獲得最新內容。本文版權歸作者和湖南心萊信息科技有限公司共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
原文作者:心萊科技CacoCode
文檔官網:docs.xin-lai.com
QQ群:
編程交流群<85318032>?
產品交流群<897857351>
總結
以上是生活随笔為你收集整理的ABP框架使用拦截器动态配置租户过滤器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多亏我缓存技术过硬!疫情防控项目上线,我
- 下一篇: 在.NET Core中用最原生的方式读取