過濾器(二)

 

         好吧咱們繼續上一篇來挖掘。基本上明白了Action過濾器其實就應該是利用AOP的思想,在Action執行中調用了咱們的過濾器方法的。就跟咱們預想你一直一致。設計模式

         過濾器是實現了,也調用了,可是這個東東是從何而來,從以前看到的代碼咱們知道,其實也就是filter調用了咱們自定義實現的過濾器,而他是怎麼找到的呢。(以前看到override,就聯想到抽象類,虛方法,但是看看貌似不是那麼簡單。)mvc

         internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func<ActionExecutedContext> continuation)

        {

            filter.OnActionExecuting(preContext);

            //此處省略N行代碼

            

            return postContext;

        }

         那麼來看filter參數的來源,往回看代碼咱們會找到在InvokeAction方法中有這麼兩個關鍵的地方(咱們只以ActionFilter爲例)less

         public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)ide

       

        FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);post

         InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);ui

 

         那來看下,FilterInfo的定義,大概就能猜到,FilterInfo中存儲的應該是咱們的全部過濾器了吧。lua

         貌似應該就是IActionFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter,這幾個就是這些過濾器須要實現的接口。從名稱就應該能看出來其功能,Action過濾器,權限過濾器,異常過濾器,結果過濾器。設計

    public class FilterInfo

    {

        private List<IActionFilter> _actionFilters = new List<IActionFilter>();

        private List<IAuthorizationFilter> _authorizationFilters = new List<IAuthorizationFilter>();

        private List<IExceptionFilter> _exceptionFilters = new List<IExceptionFilter>();

        private List<IResultFilter> _resultFilters = new List<IResultFilter>();

 

        public FilterInfo()

        {

        }

 

        public FilterInfo(IEnumerable<Filter> filters)

        {

            // evaluate the 'filters' enumerable only once since the operation can be quite expensive

            var filterInstances = filters.Select(f => f.Instance).ToList();

 

            _actionFilters.AddRange(filterInstances.OfType<IActionFilter>());

            _authorizationFilters.AddRange(filterInstances.OfType<IAuthorizationFilter>());

            _exceptionFilters.AddRange(filterInstances.OfType<IExceptionFilter>());

            _resultFilters.AddRange(filterInstances.OfType<IResultFilter>());

        }

 

        public IList<IActionFilter> ActionFilters

        {

            get { return _actionFilters; }

        }

 

        public IList<IAuthorizationFilter> AuthorizationFilters

        {

            get { return _authorizationFilters; }

        }

 

        public IList<IExceptionFilter> ExceptionFilters

        {

            get { return _exceptionFilters; }

        }

 

        public IList<IResultFilter> ResultFilters

        {

            get { return _resultFilters; }

        }

    }

                看完FilterInfo,咱們繼續往下找Filter從何而來。也就是GetFilters方法,哎呦我去,這個寫法還挺複雜的,沒事慢慢看對象

         _getFiltersThunk 是Func<ControllerContext, ActionDescriptor, IEnumerable<Filter>>個類型的委託,兩個參數一個blog

ControllerContext,一個ActionDescriptor,返回IEnumerable<Filter>。嗯,能夠看看Filter,從名稱上看可能會有關係,先記着吧

那麼咱們就從FilterProviders.Providers.GetFilters找吧。

 protected virtual FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)

        {

            return new FilterInfo(_getFiltersThunk(controllerContext, actionDescriptor));

        }

 

         private Func<ControllerContext, ActionDescriptor, IEnumerable<Filter>> _getFiltersThunk =          FilterProviders.Providers.GetFilters;

 

         public class Filter

    {

        public const int DefaultOrder = -1;

 

        public Filter(object instance, FilterScope scope, int? order)

        {

            if (instance == null)

            {

                throw new ArgumentNullException("instance");

            }

 

            if (order == null)

            {

                IMvcFilter mvcFilter = instance as IMvcFilter;

                if (mvcFilter != null)

                {

                    order = mvcFilter.Order;

                }

            }

 

            Instance = instance;

            Order = order ?? DefaultOrder;

            Scope = scope;

        }

 

        public object Instance { get; protected set; }

 

        public int Order { get; protected set; }

 

        public FilterScope Scope { get; protected set; }

    }

            先來看看FilterProviders東西吧。靜態類,其實就維護了一個FilterProviderCollection 個東東,也就是Providers屬性。看其定義,其實就是一個IFilterProvider的集合麼。看看他的GetFilters方法是如何實現的吧。還記得咱們過濾器是如何註冊的麼,以前好像忘了提這個了,這裏補上,在Global.asax文件中有這麼句話

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 註冊全局過濾器,看代碼,嗯,就那麼個意思。         

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

        {

            filters.Add(new HandleErrorAttribute());

            // Custom global action filters...

            filters.Add(new UserLoginInfoAttribute());

        }

 

         public static class GlobalFilters

    {

        static GlobalFilters()

        {

            Filters = new GlobalFilterCollection();

        }

 

        public static GlobalFilterCollection Filters { get; private set; }

    }

 

         public static class FilterProviders

    {

        static FilterProviders()

        {

            Providers = new FilterProviderCollection();

            Providers.Add(GlobalFilters.Filters);

            Providers.Add(new FilterAttributeFilterProvider());

            Providers.Add(new ControllerInstanceFilterProvider());

        }

 

        public static FilterProviderCollection Providers { get; private set; }

    }

            這時候大概能看出點眉目了吧,至少全局註冊的過濾器,這裏基本上能接上了。而後繼續往下看。FilterProviderCollection 的GetFilters方法實際上是調用了IFilterProvider的GetFilters

         public class FilterProviderCollection : Collection<IFilterProvider>

    {

        private static FilterComparer _filterComparer = new FilterComparer();

        private IResolver<IEnumerable<IFilterProvider>> _serviceResolver;

 

        public FilterProviderCollection()

        {

            _serviceResolver = new MultiServiceResolver<IFilterProvider>(() => Items);

        }

 

        public FilterProviderCollection(IList<IFilterProvider> providers)

            : base(providers)

        {

            _serviceResolver = new MultiServiceResolver<IFilterProvider>(() => Items);

        }

 

        internal FilterProviderCollection(IResolver<IEnumerable<IFilterProvider>> serviceResolver, params IFilterProvider[] providers)

            : base(providers)

        {

            _serviceResolver = serviceResolver ?? new MultiServiceResolver<IFilterProvider>(() => Items);

        }

 

        private IEnumerable<IFilterProvider> CombinedItems

        {

            get { return _serviceResolver.Current; }

        }

 

        private static bool AllowMultiple(object filterInstance)

        {

            IMvcFilter mvcFilter = filterInstance as IMvcFilter;

            if (mvcFilter == null)

            {

                return true;

            }

 

            return mvcFilter.AllowMultiple;

        }

 

        public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)

        {

            if (controllerContext == null)

            {

                throw new ArgumentNullException("controllerContext");

            }

            if (actionDescriptor == null)

            {

                throw new ArgumentNullException("actionDescriptor");

            }

 

            IEnumerable<Filter> combinedFilters =

                CombinedItems.SelectMany(fp => fp.GetFilters(controllerContext, actionDescriptor))

                    .OrderBy(filter => filter, _filterComparer);

 

            // Remove duplicates from the back forward

            return RemoveDuplicates(combinedFilters.Reverse()).Reverse();

        }

 

        private IEnumerable<Filter> RemoveDuplicates(IEnumerable<Filter> filters)

        {

            HashSet<Type> visitedTypes = new HashSet<Type>();

 

            foreach (Filter filter in filters)

            {

                object filterInstance = filter.Instance;

                Type filterInstanceType = filterInstance.GetType();

 

                if (!visitedTypes.Contains(filterInstanceType) || AllowMultiple(filterInstance))

                {

                    yield return filter;

                    visitedTypes.Add(filterInstanceType);

                }

            }

        }

 

        private class FilterComparer : IComparer<Filter>

        {

            public int Compare(Filter x, Filter y)

            {

                // Nulls always have to be less than non-nulls

                if (x == null && y == null)

                {

                    return 0;

                }

                if (x == null)

                {

                    return -1;

                }

                if (y == null)

                {

                    return 1;

                }

 

                // Sort first by order...

 

                if (x.Order < y.Order)

                {

                    return -1;

                }

                if (x.Order > y.Order)

                {

                    return 1;

                }

 

                // ...then by scope

 

                if (x.Scope < y.Scope)

                {

                    return -1;

                }

                if (x.Scope > y.Scope)

                {

                    return 1;

                }

 

                return 0;

            }

        }

    }

        

  /// <summary>

  /// 提供用於查找篩選器的接口。

  /// </summary>

  public interface IFilterProvider

  {

    /// <summary>

    /// 返回一個包含服務定位器中的全部 <see cref="T:System.Web.Mvc.IFilterProvider"/> 實例的枚舉器。

    /// </summary>

    ///

    /// <returns>

    /// 包含服務定位器中的全部 <see cref="T:System.Web.Mvc.IFilterProvider"/> 實例的枚舉器。

    /// </returns>

    /// <param name="controllerContext">控制器上下文。</param><param name="actionDescriptor">操做描述符。</param>

    IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor);

  }

  

         好吧,腦子已經基本上亂的夠嗆了,一塊兒捋一捋,ControllerActionInvoker提供了Action的執行,那麼執行方法之中提供了執行過濾器的地方,並且在執行過濾器以前,經過FilterProviders,(一個靜態類,初始化註冊了三種東西。其中包括GlobalFilters.Filters,FilterAttributeFilterProvider,ControllerInstanceFilterProvider,咱們只關注GlobalFilters.Filters)初始化註冊了全局過濾器, 而後看咱們的GlobalFilters。(也是一個靜態了,維護了全局的過濾器集合),在Global.asax中咱們已經註冊了咱們須要的過濾器,好吧這麼就貫通下來了。從全局過濾器的註冊,獲取,執行。咱們都已經看到了。

         能夠看到,代碼中應用了大量的xx Provider的方式提供一些東西,其實就是管理一個集合對象的靜態類,靜態構造中會進行一些初始化工做,而後維護了一個對應對象的集合。該集合提供了一些集合的操做和枚舉器的實現。貌似是種設計模式吧,鄙人才疏學淺,還須要查查,哪位大神指導能否指點一二。

         從咱們的分析中,咱們只看了過濾器中的一部分代碼而已,因此確定的其中還有不少咱們沒有看到。不過基本已經明白了全局過濾器的實現了,不過這篇咱們也能學到很多東東了,不過問題也更多了。好比看Controller的定義貌似也是個過濾器(實現了過濾器接口),怎麼用呢。咱們只大體研究了下Action過濾器而已,其餘的幾個過濾器是否是也要搞幾個Demo看看(猜想實現和思路應該是同樣同樣滴),FilterProviders,中註冊的其餘兩個對象是否是也是過濾器。等等。

         革命還沒有成功,研究須要繼續。

相關文章
相關標籤/搜索