前面一篇中講解了過濾器執行之前的創建,通過實現IFilterPRovider注冊到當前的HttpConfiguration里的服務容器中,當然默認的基礎服務也是有的,并且根據這些提供程序所獲得的的過濾器信息集合進行排序。本篇就會對過濾器在創建完之后所做的一系列操作進行講解。
FilterGrouping類型是ApiController類型中的私有類型,它的作用就如同它的命名一樣,用來對過濾器集合進行分組,在上一篇中我們看到,在經過調用HttpActionDescriptor類型的GetFilterPipeline()方法之后回去獲取到排序過后的過濾器信息集合Collection<FilterInfo>。下面我們看一下FilterGrouping類型定義:
示例代碼1-1
    private class FilterGrouping    {        // Fields        private List<IActionFilter> _actionFilters = new List<IActionFilter>();        private List<IAuthorizationFilter> _authorizationFilters = new List<IAuthorizationFilter>();        private List<IExceptionFilter> _exceptionFilters = new List<IExceptionFilter>();        // Methods        public FilterGrouping(IEnumerable<FilterInfo> filters)        {            foreach (FilterInfo info in filters)            {                IFilter instance = info.Instance;                Categorize<IActionFilter>(instance, this._actionFilters);                Categorize<IAuthorizationFilter>(instance, this._authorizationFilters);                Categorize<IExceptionFilter>(instance, this._exceptionFilters);            }        }        private static void Categorize<T>(IFilter filter, List<T> list) where T : class        {            T item = filter as T;            if (item != null)            {                list.Add(item);            }        }        // Properties        public IEnumerable<IActionFilter> ActionFilters        {            get            {                return this._actionFilters;            }        }        public IEnumerable<IAuthorizationFilter> AuthorizationFilters        {            get            {                return this._authorizationFilters;            }        }        public IEnumerable<IExceptionFilter> ExceptionFilters        {            get            {                return this._exceptionFilters;            }        }}在代碼1-1中我們看到在FilterGrouping類型的構造函數中便會對過濾器信息集合進行分組了,當然了分組的時候是調用FilterGrouping類型中的放吧,在Categorize()方法中就是根據實例的類型來進行判斷的,最后由FilterGrouping類型中的三個公共屬性來表示分組過后的不同類型的過濾器集合。
在上個篇幅中我們通過示例了解到過濾器管道的生成過程以及結果,我們就來看一下執行的過程,順帶再看下過濾器管道的結果是不是如上篇上所說的那樣。
先看服務器端(Selfhost)的代碼:
代碼1-2
using System.Web.Http.Controllers;using System.Web.Http.Filters;using NameSpaceControllerThree;namespace SelfHost{    class Program    {        static void Main(string[] args)        {                       HttpSelfHostConfiguration selfHostConfiguration =                new HttpSelfHostConfiguration("http://localhost/selfhost");            using (HttpSelfHostServer selfHostServer = new HttpSelfHostServer(selfHostConfiguration))            {                selfHostServer.Configuration.Routes.MapHttpRoute(                    "DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });                selfHostServer.Configuration.Services.Replace(typeof(IAssembliesResolver),                    new CustomAssembliesResolver.LoadSpecifiedAssembliesResolver());                //添加全局過濾器                selfHostServer.Configuration.Filters.Add(new WebAPIController.Filter.CustomConfigurationActionFilterAttribute());                selfHostServer.OpenAsync();                Console.WriteLine("服務器端服務監聽已開啟");                Console.Read();            }        }    }} 這里只有一個添加全局行為過濾器的這么一句代碼,其余的部分就不解釋了。
然后我們接著看控制器部分,如下示例代碼:
代碼1-3
namespace NameSpaceControllerThree{    [CustomControllerAuthorizationFilter]    [CustomControllerActionFilter]    public class WriterAndReadController : ApiController    {        [CustomActionFilter]        [CustomControllerActionAuthorizationFilter]        public string Get()        {            StringBuilder strBuilder = new StringBuilder();            HttpActionDescriptor actionDescriptor = this.Configuration.Services.GetActionSelector().SelectAction(this.ControllerContext);            System.Collections.ObjectModel.Collection<FilterInfo> filtersInfo = actionDescriptor.GetFilterPipeline();            foreach (var filter in filtersInfo)            {                strBuilder.AppendLine("【FilterName:"+filter.Instance.GetType().Name+",FilterScope:"+filter.Scope.ToString()+"】");            }            return strBuilder.ToString();        }    }}對于上一篇,這里的修改只是在控制器類型和控制器方法上各自新增了一個授權過濾器,下面我們就來看一下過濾器的定義,如下示例代碼:
代碼1-4
/// <summary>    /// 全局的行為過濾器    /// </summary>    public class CustomConfigurationActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器級行為過濾器    /// </summary>    public class CustomControllerActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器方法級行為過濾器    /// </summary>    public class CustomActionFilterAttribute : FilterAttribute, IActionFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器級授權訪問過濾器    /// </summary>    public class CustomControllerAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }    }    /// <summary>    /// 控制器方法級授權訪問過濾器    /// </summary>    public class CustomControllerActionAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter    {        public Task<System.Net.Http.HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<System.Net.Http.HttpResponseMessage>> continuation)        {            Console.WriteLine(this.GetType().Name);            return continuation();        }}在代碼1-4中,我們可以看到代碼1-3中所有使用到的過濾器類型和代碼1-2中添加全局過濾器類型。
現在我們看一下最后的結果
圖1

黑色框的結果為SelfHost服務器端過濾器執行過程的輸出,在代碼1-4中我們可以看到,這個得出的一個結論是授權過濾器不管是什么應用范圍的都是優于行為過濾器的,而在同一種類型的過濾器中是根據應用范圍來確定執行順序的,這個跟下面的瀏覽器里的內容有點關系,瀏覽器里顯示的就是所有過濾器在排序后的管道里的樣子,可以看到管道里單純的就是按照應用范圍的級別來排序的,至于這個過濾器是什么類型在處理排序的時候則是一點都不關心的。
首先看一下如下示意圖,可以代表了在控制器執行的過程中過濾器的執行過程。
圖2

上面通過示例來說明了過濾器的執行過程,現在我們來看一下在框架的源碼中是什么樣的,因為在過濾器執行過程中還包含了其它方面的知識點,所以這個是遲早都要看的,下面我們就來看一下吧。
代碼1-5
return InvokeAction
新聞熱點
疑難解答