ABP 配置全局數據過濾器


可以不看下面內容,直接看這:https://www.cnblogs.com/MindSharing/p/11283914.html

================================

ABP官方數據過濾的地址:https://aspnetboilerplate.com/Pages/Documents/Data-Filters

中文可以看這個:https://aspnetboilerplate.com/Pages/Documents/Data-Filters

看完后最大問題就是,自定義的數據過濾和UOW中事務是在一起的

using (CurrentUnitOfWork.EnableFilter("PersonFilter"))
{
    using(CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42))
    {
        var phones = _phoneRepository.GetAllList();
        //...
    }
}

總不可能每次我寫服務的時候,都在方法里面寫一串這個代碼吧,那這樣也沒方便多少

所以可以考慮使用我方法來給過濾器全局設置一個值。

我的應用場景是這樣的,我的項目登錄的時候會讓用戶選擇一個專業,所有數據都是這個專業下的,什么建築啊,結構啊

為了實現這個篩選,先還是需要建立過濾器,在Core項目添加一個接口

    public interface IHasMajor
    {
        string Major { get; set; }
    }

 在EF項目中的DbContext.cs 中注冊 過濾器

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);


            modelBuilder.Filter("MajorFilter", (IHasMajor entity, string major) => entity.Major == major, "");

        }

 在你需要篩選專業的實體里面實現這個接口

  [Table("DictionaryInfo")]
    public class DictionaryInfo : FullAuditedEntity, IHasMajor
    {
        public virtual int? ParentId { get; set; }

        public virtual string Value { get; set; }

        public virtual string Description { get; set; }

        public virtual DictionaryInfo ParentDictionaryInfo { get; set; }

        public virtual ICollection<DictionaryInfo> ChildDictionaryInfos { get; set; }

        public virtual string Major { get; set; }
    }

  好了下面就是關鍵的了,傳統做法,我們就是在服務里面設置數據過濾的參數

        public async Task<GetDictionaryInfoOutput> GetAllDictionary()
        {
            using (CurrentUnitOfWork.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, AbpSession.GetMajor()))
            {
                List<DictionaryInfo> dictionaries = await _dictionaryInfoRepository.GetAllListAsync();
                var result = new GetDictionaryInfoOutput
                {
                    Dictionary = dictionaries.MapTo<List<DictionaryInfoDto>>()
                };
                return result;
            }

        }

  這種方式感覺很不優雅,改用攔截器來自動為每個服務注入 過濾器參數,

ABP 官方對攔截器他也給了個例子,可以看這個

https://www.codeproject.com/Articles/1080517/Aspect-Oriented-Programming-using-Interceptors-wit

添加個一個攔截器,在應用層

    public class FilterInterceptor : IInterceptor
    {
        private readonly IAbpSession _abpSession;

        private readonly IUnitOfWork _unitOfWork;

        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public FilterInterceptor(
            IUnitOfWork unitOfWork
            , IAbpSession abpSession
            , IUnitOfWorkManager unitOfWorkManager)
        {
            Logger = NullLogger.Instance;
            _unitOfWork = unitOfWork;
            _abpSession = abpSession;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public ILogger Logger { get; set; }

        public void Intercept(IInvocation invocation)
        {
            string major = _abpSession.GetMajor();

            _unitOfWorkManager.Current.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, major);

            //Executing the actual method
            invocation.Proceed();
        }

    }

  

這里面有一個主意地方,攔截器請注入IUnitOfWorkManager ,而不是注入IUnitOfWork ,后者設置參數了,沒效果

然后再注冊攔截器,在應用層添加一個文件

 public static class InterceptorRegistrar
    {
        public static void Initialize(IKernel kernel)
        {
            kernel.ComponentRegistered += Kernel_ComponentRegistered;
        }

        private static void Kernel_ComponentRegistered(string key, IHandler handler)
        {
            if (typeof(IApplicationService).IsAssignableFrom(handler.ComponentModel.Implementation))
            {
                handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(FilterInterceptor)));
            }
        }
    }

  在應用層的ApplicationModule.cs 文件里面的PreInitialize方法里面

public override void PreInitialize()
        {
            InterceptorRegistrar.Initialize(IocManager.IocContainer.Kernel);
        }

  好這樣就注冊完了,可以試試服務層每個方法都能自動判斷專業了,把服務里面手動設置篩選參數的地方都可以去掉了

     public async Task<GetDictionaryInfoOutput> GetAllDictionary()
        {
            //using (CurrentUnitOfWork.SetFilterParameter(SysConsts.DataFilter.MajorFilter, SysConsts.DataFilter.MajorParameter, AbpSession.GetMajor()))
            //{
                List<DictionaryInfo> dictionaries = await _dictionaryInfoRepository.GetAllListAsync();
                var result = new GetDictionaryInfoOutput
                {
                    Dictionary = dictionaries.MapTo<List<DictionaryInfoDto>>()
                };
                return result;
            //}

        }

  

專業的值是存在session里面的,如何把自己想要的值存到session 里面,可以參照這篇文章

http://www.jianshu.com/p/930c10287e2a

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM