zoukankan      html  css  js  c++  java
  • 过滤器(二)

             好吧我们继续上一篇来挖掘。基本上明白了Action过滤器其实就应该是利用AOP的思想,在Action执行中调用了我们的过滤器方法的。就跟我们预想你一直一致。

             过滤器是实现了,也调用了,但是这个东东是从何而来,从之前看到的代码我们知道,其实也就是filter调用了我们自定义实现的过滤器,而他是怎么找到的呢。(之前看到override,就联想到抽象类,虚方法,可是看看貌似不是那么简单。)

             internal static ActionExecutedContext InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func<ActionExecutedContext> continuation)
    
            {
    
                filter.OnActionExecuting(preContext);
    
                //此处省略N行代码
    
                
    
                return postContext;
    
            }

             那么来看filter参数的来源,往回看代码我们会找到在InvokeAction方法中有这么两个关键的地方(我们只以ActionFilter为例)

             public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)

           

            FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor);

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

             那来看下,FilterInfo的定义,大概就能猜到,FilterInfo中存储的应该是我们的所有过滤器了吧。

             貌似应该就是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>>个类型的委托,两个参数一个

    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,中注册的其他两个对象是不是也是过滤器。等等。

             革命尚未成功,研究需要继续。

  • 相关阅读:
    4、Work-Queue
    一个简单servlet容器
    一个简单的Web服务器
    jersey实现RESTful接口PUT方法JSON数据传递
    Java数据库连接组件C3P0和DBCP
    C/S架构和B/S架构
    一些同样适用于人生的计算机原理
    网络编程初探--使用UDP协议的简易聊天室
    IO练习--按字节截取字符串
    IO包中的其他类总结
  • 原文地址:https://www.cnblogs.com/superCow/p/3803056.html
Copyright © 2011-2022 走看看