好吧咱們繼續上一篇來挖掘。基本上明白了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,中註冊的其餘兩個對象是否是也是過濾器。等等。
革命還沒有成功,研究須要繼續。