过滤器(二)

 

         好吧我们继续上一篇来挖掘。基本上明白了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,中注册的其他两个对象是不是也是过滤器。等等。

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

posted on 2014-06-22 21:06  Super Cow  阅读(194)  评论(0编辑  收藏  举报

导航