使用Autofac来注入Web API HttpConfiguration中定义的服务

您所在的位置:网站首页 错误代码0x8007025d解决方法 使用Autofac来注入Web API HttpConfiguration中定义的服务

使用Autofac来注入Web API HttpConfiguration中定义的服务

#使用Autofac来注入Web API HttpConfiguration中定义的服务| 来源: 网络整理| 查看: 265

百度翻译此文   有道翻译此文 问题描述

When using Autofac with ASP.NET Web API, is there any way to resolve dependencies using the services registered in HttpConfiguration or even the HttpConfiguration itself. For instance, I would like to have a controller with a constructor that receives the config's registered ITraceWriter or the HttpConfiguration itself. I know that the configuration is available in the action methods, but I would like to use it in the constructor.

Thanks.

edit 1

I've found a way to make the current configuration resolvable through the dependency scope, inspired on the Autofac RegisterHttpRequestMessage extension method: register a controller activator that adds the current configuration to the current request scope.

class CurrentConfigurationActivator : IHttpControllerActivator { private readonly IHttpControllerActivator _innerActivator; public CurrentConfigurationActivator(IHttpControllerActivator innerActivator) { _innerActivator = innerActivator; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { var scope = request.GetDependencyScope(); var requestScope = scope.GetRequestLifetimeScope(); if (requestScope != null) { var registry = requestScope.ComponentRegistry; var builder = new ContainerBuilder(); builder.Register(c => controllerDescriptor.Configuration).InstancePerRequest(); builder.Update(registry); } return _innerActivator.Create(request, controllerDescriptor, controllerType); } }

It does work, but is there a better way? Having to decorate the existing activator seems a little bit fragile. Regarding the services registered in the configuration (e.g. ITraceWriter), a way is to manually register each one on the dependency scope using the same technique.

推荐答案

The easiest way to do this would be to create a simple Autofac module that does the resolution for you. A snippet might look like this:

public class ServiceModule : Module { protected override void Load(ContainerBuilder builder) { builder.Register(c => c.Resolve() .GetConfiguration()) .As(); builder.Register(c => c.Resolve() .Services .GetService(IApiExplorer) as IApiExplorer) .As(); // Rinse and repeat for every service you want to resolve. } }

Doing it that way would mean you don't need to use any fancy controller activator or whatever - the whole thing would hinge off of the already-working integration that Autofac has for resolving the current request message.

builder.RegisterHttpRequestMessage(config); builder.RegisterModule();

Note that since it all hinges off of the current request message, these won't be resolvable outside a request. If you need them resolvable outside a request, then you can attach the module/resolutions directly to a specific configuration object:

public class ServiceModule : Module { private HttpConfiguration _config; public ServiceModule(HttpConfiguration config) { this._config = config; } protected override void Load(ContainerBuilder builder) { builder.RegisterInstance(this._config) .As(); builder.Register(c => c.Resolve() .Services .GetService(IApiExplorer) as IApiExplorer) .As(); // Rinse and repeat for every service you want to resolve. } }

And pass the config in during module construction.

builder.RegisterHttpRequestMessage(config); builder.RegisterModule(new ServiceModule(config));

The second way will let you resolve things outside a request. Either way will work, it just depends on what you want to do.

If you have something in the pipeline that may somehow change up the config on a per request basis and it's important to get that request's configuration/services, the first way is better. If you don't have that complex of a case, then the second way may be better.

The key is that you want to resolve dependencies using the services registered in HttpConfiguration, not that you want the services in HttpConfiguration to be resolved by Autofac. There's an important difference - the services in HttpConfiguration are largely singletons and are sometimes cached because they're assumed to be singletons. If you try to change that, like trying to register some service as InstancePerRequest or some such, you may run into unexpected problems.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3