ASP.NET Core中的ActionFilter與DI

1、簡介

  前幾篇文章都是講ASP.NET Core MVC中的依賴注入(DI)與擴展點的,也許你們都發如今ASP.NET CORE中全部的組件都是經過依賴注入來擴展的,並且面向一組功能就會有一組接口或抽象工廠來擴展功能,就如IControllerActivator這樣的功能點在上篇文章(查看.NET Core源代碼經過Autofac實現依賴注入到Controller屬性)中也提到了,今天咱們主要介紹一個大相似的擴展點,ASP.NET Core MVC中爲咱們提供了新的機制爲Action Filters(也就是過濾器)進行依賴注入的擴展。html

2、過濾器依賴注入

  在ASP.NET Core MVC中,框架中爲咱們提供了類型爲 IFilter 的 Attributes 來裝飾Action,用於攔截Action請求,這有在之前的版本中就有了,可是若是咱們想結合依賴注入使用的話要使用IFilterFactory接口來擴展Action Filter的建立過程。git

  2.1 IFilterFactory接口定義

public interface IFilterFactory : IFilter
{
    IFilter CreateInstance([NotNull] IServiceProvider serviceProvider);
}

 

  咱們想要建立一個Filter Attribute並須要依賴注入的話通常想要的代碼爲:github

複製代碼
public class FilterClass : ActionFilterAttribute  
{
  public FilterClass(IDependency1 dependency1, IDependency2 dependency2)
  {
    // ...use dependencies
  }
}
複製代碼

 

  ASP.NET Core MVC中爲咱們提供了兩種簡單的IFilterFactory ServiceFilterAttribute 和 TypeFilterAttribute 。來個例子看看怎麼使用。框架

複製代碼
public class HomeController: Controller  
{
    [TypeFilter(typeof(FilterClass))]
    [ServiceFilter(typeof(FilterClass))]
    public IActionResult Index()
    {
        return View();
    }
}
複製代碼

  2.2 ServiceFilterAttribute 

   其實看到名字,有些朋友就能想到了,它是基於依賴注入的一個IFilterFactory,Service這個詞強化了它是一個經過獲取服務來實現依賴注入的,你們想到了什麼?是否是GetService()? 沒錯,其實它的機制就是這個。ide

     要使用ServiceFilter就必須在依賴注入容器裏註冊對應的類型,好比下面的例子就要先將FilterClass類型註冊到IOC容器裏。post

public void ConfigureServices(IServiceCollection services)
{
      services.AddSingleton<FilterClass>();
 
      services.AddMvc()
}

  固然若是FilterClass類型的構造器須要注入類型時,也須要在IOC容器裏進行註冊纔可使用。學習

  咱們來看下ServiceFilterAttribute的源代碼:ui

複製代碼
public class ServiceFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
    public ServiceFilterAttribute([NotNull] Type type)
    {
        ServiceType = type;
    }

    public Type ServiceType { get; private set; }

    public int Order { get; set; }

    public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
    {
        var service = serviceProvider.GetRequiredService(ServiceType);

        var filter = service as IFilter;
        if (filter == null)
        {
            throw new InvalidOperationException(Resources.FormatFilterFactoryAttribute_TypeMustImplementIFilter(
                typeof(ServiceFilterAttribute).Name,
                typeof(IFilter).Name));
        }

        return filter;
    }
}
複製代碼

  2.3 TypeFilterAttribute

   固然你也能夠選擇使用這個相似於ServiceFilter過濾器的TypeFilter過濾器,它也一樣實現了IFilterFactory接口,並能夠經過它建立出可以使用依賴注入的過濾器來。之因此叫TypeFilter就是由於它並不須要在依賴注入容器裏註冊類型就能建立出過濾器,  咱們來看下它的代碼:this

複製代碼
public class TypeFilterAttribute : Attribute, IFilterFactory, IOrderedFilter
{
    private ObjectFactory factory;

    public TypeFilterAttribute([NotNull] Type type)
    {
        ImplementationType = type;
    }

    public object[] Arguments { get; set; }

    public Type ImplementationType { get; private set; }

    public int Order { get; set; }

    public IFilter CreateInstance([NotNull] IServiceProvider serviceProvider)
    {
        if (this.factory == null)
        {
            var argumentTypes = Arguments?.Select(a => a.GetType())?.ToArray();

            this.factory = ActivatorUtilities.CreateFactory(ImplementationType, argumentTypes ?? Type.EmptyTypes);
        }

        return (IFilter)this.factory(serviceProvider, Arguments);
    }
}
複製代碼

3、結語

  相信看過上一篇文章的朋友都注意到了ServiceProviderActivatorUtilities 的不一樣,本文中的ServiceFilterAttribute和 TypeFilterAttribute 原理上也是經過它們來建立Filter的,因此使用場景就看你們如何來使用。其實最近看.NET Core的源代碼,看到的處處都是接口、工廠使用依賴注入造成擴展點的例子,其實微軟之前代碼的擴展點也挺多的,只是API並不那麼開放,ASP.NET Core中咱們看到了一個"開放"的框架。spa

 

  GitHub:https://github.com/maxzhang1985/YOYOFx  若是覺還能夠請Star下, 歡迎一塊兒交流。

 

  .NET Core 開源學習羣: 214741894  

 

 
 
6
0
 
 
 
« 上一篇:  查看.NET Core源代碼經過Autofac實現依賴注入到Controller屬性
» 下一篇:  解決ASP.NET Core Mvc文件上傳限制問題
相關文章
相關標籤/搜索