前几篇文章都是讲ASP.NET Core MVC中的依赖注入(DI)与扩展点的,也许你们都发如今ASP.NET CORE中全部的组件都是经过依赖注入来扩展的,并且面向一组功能就会有一组接口或抽象工厂来扩展功能,就如IControllerActivator这样的功能点在上篇文章(查看.NET Core源代码经过Autofac实现依赖注入到Controller属性)中也提到了,今天咱们主要介绍一个大相似的扩展点,ASP.NET Core MVC中为咱们提供了新的机制为Action Filters(也就是过滤器)进行依赖注入的扩展。html
在ASP.NET Core MVC中,框架中为咱们提供了类型为 IFilter 的 Attributes 来装饰Action,用于拦截Action请求,这有在之前的版本中就有了,可是若是咱们想结合依赖注入使用的话要使用IFilterFactory接口来扩展Action Filter的建立过程。git
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(); } }
其实看到名字,有些朋友就能想到了,它是基于依赖注入的一个IFilterFactory,Service这个词强化了它是一个经过获取服务来实现依赖注入的,你们想到了什么?是否是GetService()? 没错,其实它的机制就是这个。ide
要使用ServiceFilter就必须在依赖注入容器里注册对应的类型,好比下面的例子就要先将FilterClass类型注册到IOC容器里。学习
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<FilterClass>(); services.AddMvc() }
固然若是FilterClass类型的构造器须要注入类型时,也须要在IOC容器里进行注册才可使用。ui
咱们来看下ServiceFilterAttribute的源代码:this
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; } }
固然你也能够选择使用这个相似于ServiceFilter过滤器的TypeFilter过滤器,它也一样实现了IFilterFactory接口,并能够经过它建立出可以使用依赖注入的过滤器来。之因此叫TypeFilter就是由于它并不须要在依赖注入容器里注册类型就能建立出过滤器, 咱们来看下它的代码:spa
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); } }
相信看过上一篇文章的朋友都注意到了ServiceProvider和ActivatorUtilities 的不一样,本文中的ServiceFilterAttribute和 TypeFilterAttribute 原理上也是经过它们来建立Filter的,因此使用场景就看你们如何来使用。其实最近看.NET Core的源代码,看到的处处都是接口、工厂使用依赖注入造成扩展点的例子,其实微软之前代码的扩展点也挺多的,只是API并不那么开放,ASP.NET Core中咱们看到了一个"开放"的框架。code
GitHub:https://github.com/maxzhang1985/YOYOFx 若是觉还能够请Star下, 欢迎一块儿交流。
.NET Core 开源学习群: 214741894