天天看点

Autofac与WebApi集成Autofac原理如何将Autofac与Web API集成?Autofac功能详解

目录

Autofac原理

如何将Autofac与Web API集成?

Autofac功能详解

1.HttpConfiguration

2.控制器

3.解析器

4.过滤器

1.注册过滤器提供程序

2.实现过滤器接口

3.注册过滤器

4.过滤器覆盖

5为什么我们使用非标准的过滤器接口

6.标准Web API筛选器属性是单例

7实例过滤器不会被注入

5.模型绑定器

1.注册绑定器提供程序

2注册模型绑定器

3使用ModelBinderAttribute标记参数

Autofac原理

寻找到相关实例,将其赋给接口对象。比如说,我们在调用方使用了一堆接口,然后引用了一个DLL,这个DLL包含了实现这些接口的实例,那么Autofac就自动从这个DLL中提取出这些实例,赋给接口对象。这一切都是Autofac自动完成的。

如何将Autofac与Web API集成?

1需要引用Web API集成NuGet包

2修改Global.axax文件

  1. 注册您的控制器并设置依赖关系解析器。
  2. 也可以选择启用其他功能。

如下:

protected void Application_Start()
{
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
                       

            //扫描特定名称的程序集并一次性注册控制器
            var assemblies = BuildManager.GetReferencedAssemblies()
                .Cast<Assembly>()
                .Where(r => r.FullName.StartsWith("CsdnNet."))
                .ToArray();

            var builder = new ContainerBuilder();
            //得到你的HttpConfiguration.
            var config = GlobalConfiguration.Configuration;


            builder.RegisterAssemblyModules(assemblies);
            //注册您的Web API控制器.
            builder.RegisterApiControllersAndInterface(assemblies);
            builder.RegisterConsumes(assemblies);
            builder.RegisterRemotingService(assemblies);
            builder.RegisterCrossService(assemblies);
            builder.RegisterDao(assemblies);
            builder.RegisterHotelBaseAutofacFilter();
            //可选:注册Autofac过滤器、筛选器提供程序.
            builder.RegisterWebApiFilterProvider(config);
            //可选:注册Autofac模型绑定器提供程序
            builder.RegisterWebApiModelBinderProvider();

            //将依赖关系解析器设置为Autofac。
            var container = builder.Build();//容器
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);//让Web API知道它应该使用AutofacWebApiDependencyResolver(解析器)找到服务
            
            var csl = new AutofacServiceLocator(container);
            ServiceLocator.SetLocatorProvider(() => csl);
}
           

其中,Autofac为我们提供了HttpConfiguration 、控制器、解析器、过滤器、模型绑定器…

Autofac功能详解

***以下内容摘自:https://blog.csdn.net/WuLex/article/details/78808541

1.HttpConfiguration

在Web API中,设置应用程序需要您更新

HttpConfiguration

对象的属性并设置值。 根据您的应用程序托管方式,您获得此配置的方式可能有所不同。

1.对于标准的IIS托管,

HttpConfiguration

GlobalConfiguration.Configuration

  1. var builder = new ContainerBuilder();  
  2. var config = GlobalConfiguration.Configuration;  
  3. builder.RegisterApiControllers(Assembly.GetExecutingAssembly());  
  4. var container = builder.Build();  
  5. config.DependencyResolver = new AutofacWebApiDependencyResolver(container);  

2.对于自托管,

HttpConfiguration

是您的

HttpSelfHostConfiguration

实例

  1. var builder = new ContainerBuilder();  
  2. var config = new HttpSelfHostConfiguration("http://localhost:8080");  
  3. builder.RegisterApiControllers(Assembly.GetExecutingAssembly());  
  4. var container = builder.Build();  
  5. config.DependencyResolver = new AutofacWebApiDependencyResolver(container);  

对于OWIN集成,

HttpConfiguration

是您在应用程序启动类中创建并传递给Web API中间件的一个。

  1. var builder = new ContainerBuilder();  
  2. var config = new HttpConfiguration();  
  3. builder.RegisterApiControllers(Assembly.GetExecutingAssembly());  
  4. var container = builder.Build();  
  5. config.DependencyResolver = new AutofacWebApiDependencyResolver(container);  

2.控制器

在应用程序启动时,在构建Autofac容器的同时,您应该注册您的Web API控制器及其依赖项。 这通常发生在OWIN启动类或

Global.asax

Application_Start

方法中。

默认情况下,实现

IHttpController

的类型和具有后缀

Controller

的名称将被注册。

  1. var builder = new ContainerBuilder();  
  2. //.您可以使用程序集扫描一次注册控制器...  
  3. builder.RegisterApiControllers(Assembly.GetExecutingAssembly());  
  4. // ...或者您可以手动注册个人控制器  
  5. builder.RegisterType<ValuesController>().InstancePerRequest();  

如果您的控制器不遵循标准命名约定,则可以选择使用

RegisterApiControllers

方法的重载提供自定义后缀。

  1. //您还可以使用程序集扫描以自定义后缀注册控制器  
  2. builder.RegisterApiControllers("MyCustomSuffix", Assembly.GetExecutingAssembly());  

3.解析器

在构建你的容器之后,将它传递给

AutofacWebApiDependencyResolver

类的新实例。 将新的解析器附加到您的

HttpConfiguration.DependencyResolver

,让Web API知道它应该使用

AutofacWebApiDependencyResolver

找到服务。 这是Autofac的

IDependencyResolver

接口的实现。

  1. var container = builder.Build();  
  2. config.DependencyResolver = new AutofacWebApiDependencyResolver(container);  

4.过滤器

因为属性是通过反射API创建的,所以你不能自己调用构造函数。 除了属性注入特性之外,没有别的选择。 与Web API的Autofac集成提供了一种机制,允许您创建实现过滤器接口(

IAutofacActionFilter

IAutofacAuthorizationFilter

IAutofacExceptionFilter

)的类,并使用容器构建器上的注册语法将它们连接到所需的控制器或操作方法。

1.注册过滤器提供程序

您需要注册Autofac筛选器提供程序实现,因为它可以根据注册完成筛选器的配置工作。 这是通过调用容器生成器上的

RegisterWebApiFilterProvider

方法并提供一个

HttpConfiguration

实例来完成的。

  1. var builder = new ContainerBuilder();  
  2. builder.RegisterWebApiFilterProvider(config);  

2.实现过滤器接口

而不是从现有的Web API过滤器属性派生出来,而是实现在集成中定义的适当的过滤器接口。 下面的过滤器是一个动作过滤器,并实现

IAutofacActionFilter

而不是

System.Web.Http.Filters.IActionFilter

  1. public class LoggingActionFilter : IAutofacActionFilter  
  2. {  
  3.   readonly ILogger _logger;  
  4.   public LoggingActionFilter(ILogger logger)  
  5.   {  
  6.     _logger = logger;  
  7.   }  
  8.   public Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)  
  9.   {  
  10.     _logger.Write(actionContext.ActionDescriptor.ActionName);  
  11.     return Task.FromResult(0);  
  12.   }  
  13.   public Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)  
  14.   {  
  15.     _logger.Write(actionExecutedContext.ActionContext.ActionDescriptor.ActionName);  
  16.     return Task.FromResult(0);  
  17.   }  
  18. }  

请注意,示例中没有运行实际的异步代码,因此它将返回

Task.FromResult(0)

,这是返回“空任务”的常用方法。如果您的过滤器确实需要异步代码,则可以返回一个真实的

Task

对象或 像任何其他异步方法一样使用

async/await

代码。

3.注册过滤器

为了执行过滤器,您需要将其注册到容器中,并通知哪个控制器以及可选的操作应该成为目标。 这是使用以下

ContainerBuilder

扩展方法完成的:

  1. AsWebApiActionFilterFor<TController>()  
  2. AsWebApiActionFilterOverrideFor<TController>()  
  3. AsWebApiAuthorizationFilterFor<TController>()  
  4. AsWebApiAuthorizationOverrideFilterFor<TController>()  
  5. AsWebApiAuthenticationFilterFor<TController>()  
  6. AsWebApiAuthenticationOverrideFilterFor<TController>()  
  7. AsWebApiExceptionFilterFor<TController>()  
  8. AsWebApiExceptionOverrideFilterFor<TController>()  

这些方法需要控制器类型的泛型类型参数,以及一个可选的lambda表达式,用于指示过滤器应用于控制器上的特定方法。 如果不提供lambda表达式,则过滤器将应用于控制器上的所有操作方法,方法与在控制器级别放置基于属性的过滤器相同。

您可以根据需要应用尽可能多的过滤器。 注册一种类型的过滤器不会删除或替换以前注册的过滤器。

在下面的示例中,过滤器正在应用于

ValuesController

上的Get操作方法。

  1. var builder = new ContainerBuilder();  
  2. builder.Register(c => new LoggingActionFilter(c.Resolve<ILogger>()))  
  3.     .AsWebApiActionFilterFor<ValuesController>(c => c.Get(default(int)))  
  4.     .InstancePerRequest();  

将过滤器应用于需要参数的操作方法时,请在您的lambda表达式中使用参数的数据类型为

default

的关键字作为占位符。例如,上面例子中的

Get

操作方法需要一个

int

参数,并使用

default(int)

作为lambda表达式中的强类型占位符。

也可以在通用类型参数中提供基本控制器类型,以将过滤器应用于所有派生控制器。此外,还可以使您的操作方法的

lambda

表达式针对基本控制器类型上的方法,并将其应用于所有派生控制器上的该方法。

4.过滤器覆盖

在注册过滤器时,有像

AsWebApiActionFilterFor<TController>()

这样的基本注册方法,并覆盖像

AsWebApiActionFilterOverrideFor<TController>()

这样的注册方法。重写方法的要点是提供一种方法来确保首先执行某些过滤器。您可以根据需要进行多次覆盖 - 这些不是替换筛选器,只是首先运行的筛选器。

过滤器将按以下顺序运行:

  1. Controller-scoped overrides  
  2. Action-scoped overrides  
  3. Controller scoped filters  
  4. Action scoped filters  

5为什么我们使用非标准的过滤器接口

如果您想知道为什么要引入特殊的接口,那么在Web API中查看

IActionFilter

接口的签名时,这应该会变得更加明显。

  1. public interface IActionFilter : IFilter  
  2. {  
  3.   Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation);  
  4. }  

现在将其与您需要实现的Autofac接口进行比较

  1. public interface IAutofacActionFilter  
  2. {  
  3.   Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken);  
  4.   Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken);  
  5. }  

问题是

OnActionExecutingAsync

OnActionExecutedAsync

方法实际上是在

ActionFilterAttribute

而不是在

IActionFilter

接口上定义的。 在Web API中广泛使用

System.Threading.Tasks

命名空间意味着链接返回任务以及属性中的相应错误处理实际上需要大量代码(

ActionFilterAttribute

包含近100行代码)。 这绝对不是你想要处理自己的事情。

Autofac引入了新的接口,使您能够专注于实现过滤器的代码,而不是所有的管道。 在内部,它创建实际的Web API属性的自定义实例,从容器中解析过滤器实现,并在适当的时候执行它们。

创建内部属性包装的另一个原因是支持过滤器的

InstancePerRequest

生存期范围。 

6.标准Web API筛选器属性是单例

您可能会注意到,如果您使用标准Web API筛选器,则无法使用

InstancePerRequest

依赖项。

与MVC中的过滤器提供程序不同,Web API中的过滤器提供程序不允许指定不应该的缓存过滤器实例。这意味着Web API中的所有过滤器属性都是单一实例,它们在应用程序的整个生命周期中都存在。

如果您试图在过滤器中获取每个请求的依赖关系,那么只有在使用Autofac过滤器接口的情况下才能使用。使用标准的Web API过滤器,依赖关系将被注入一次 - 第一次解析过滤器 - 而不再解析一次。

如果您无法使用Autofac接口,并且您的过滤器中需要每个请求或每个依赖于实例的服务,则必须使用服务位置。幸运的是,Web API使获取当前的请求范围变得非常简单 - 它和

HttpRequestMessage

一起。

以下是使用Web API 

IDependencyScope

的服务位置来获取每个请求相关性的过滤器示例:

  1. public interface ServiceCallActionFilterAttribute : ActionFilterAttribute  
  2. {  
  3.   public override void OnActionExecuting(HttpActionContext actionContext)  
  4.   {  
  5.     //获取请求生存期范围,以便解析服务  
  6.     var requestScope = actionContext.Request.GetDependencyScope();  
  7.     //解析您想要使用的服务  
  8.     var service = requestScope.GetService(typeof(IMyService)) as IMyService;  
  9.     //在过滤器中完成剩下的工作  
  10.     service.DoWork();  
  11.   }  
  12. }  

7实例过滤器不会被注入

设置过滤器时,可能需要手动将过滤器添加到集合中,如下所示:

config.Filters.Add(new MyActionFilter());  

Autofac不会注入以这种方式注册的过滤器的属性。 这与使用

RegisterInstance

将对象的预构造实例放入Autofac时有些类似 - Autofac不会注入或修改预构造的实例。 对于预先构建并添加到过滤器集合中的过滤器实例也是如此。 与属性过滤器一样(如上所述),您可以通过使用服务位置而不是属性注入来解决此问题。

5.模型绑定器

通过依赖注入提供模型绑定器

与Web API的Autofac集成提供了使用依赖注入来解析模型绑定器的能力,并将绑定器与使用fluent 接口的类型相关联。

1.注册绑定器提供程序

您需要注册Autofac模型绑定器提供程序,以便在需要时可以解析任何已注册的

IModelBinder

实现。 这是通过调用容器生成器上的

RegisterWebApiModelBinderProvider

方法来完成的。

  1. var builder = new ContainerBuilder();  
  2. builder.RegisterWebApiModelBinderProvider();  

2注册模型绑定器

一旦你已经实现了

System.Web.Http.ModelBinding.IModelBinder

来处理绑定的问题,使用Autofac注册它,让Autofac知道哪些类型应该绑定使用该绑定器。

  1. builder  
  2.   .RegisterType<AutomobileBinder>()  
  3.   .AsModelBinderForTypes(typeof(CarModel), typeof(TruckModel));  

3使用

ModelBinderAttribute

标记参数

即使已经注册了模型绑定器,仍然需要使用

[ModelBinder]

属性标记参数,以便Web API知道使用模型绑定器而不是媒体类型格式化程序来绑定模型。 您不必再指定模型绑定器类型,但您必须使用该属性标记该参数。 Web API文档中也提到了这一点。

public HttpResponseMessage Post([ModelBinder] CarModel car) { ... }