使用Autofac注入在网页API HttpConfiguration定义的服务 [英] Using Autofac to inject services defined in Web API HttpConfiguration

查看:341
本文介绍了使用Autofac注入在网页API HttpConfiguration定义的服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用Autofac使用的ASP.NET Web API,有没有什么办法来解决使用 HttpConfiguration 注册的服务或依赖甚至 HttpConfiguration 本身。
举例来说,我想有一个控制器接收构造的配置的注册 ITraceWriter HttpConfiguration 本身。
我知道的配置是在动作可用的方法,但我想在构造函数中使用它。

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.

感谢。

我已经找到了一种方法,使当前配置通过依赖范围解析,对Autofac启发 RegisterHtt prequestMessage 扩展方法:注册一个​​控制器激活了将当前的配置在当前请求范围。

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);
    }
}

它的工作,但有一个更好的办法?其装饰现有的激活似乎有点脆弱。
至于在配置中注册的服务(例如 ITraceWriter ),一个办法就是手动注册每一个使用相同的技术依赖范围。

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.

推荐答案

做到这将是创建一个简单的Autofac模块,做该决议对你的最简单方法。一个片段可能是这样的:

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<HttpRequestMessage>()
                        .GetConfiguration())
           .As<HttpConfiguration>();
    builder.Register(c =>
                       c.Resolve<HttpConfiguration>()
                        .Services
                        .GetService(IApiExplorer) as IApiExplorer)
           .As<IApiExplorer>();

    // Rinse and repeat for every service you want to resolve.
  }
}

做这种方式将意味着你不需要使用任何花哨的控制器激活或其他 - 整个事情将取决于掉已经工作的整合是Autofac对解决当前请求的消息

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<ServiceModule>();

请注意,由于这一切取决于关闭当前请求消息,这不会是解析请求外即可。如果你需要他们解析的请求之外,则您可以直接连接模块/决议具体的配置对象:

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<HttpConfiguration>();
    builder.Register(c =>
                       c.Resolve<HttpConfiguration>()
                        .Services
                        .GetService(IApiExplorer) as IApiExplorer)
           .As<IApiExplorer>();

    // 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.

关键是,你要的使用HttpConfiguration 注册的服务解决依赖关系,而不是要在HttpConfiguration服务由Autofac解决。这里有一个重要的区别 - HttpConfiguration 服务主要单身并有时缓存,因为他们认为是单身。如果试图改变这种状况,就像试图注册一些服务为 InstancePerRequest 或一些这样的,你可能会遇到意想不到的问题。

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.

这篇关于使用Autofac注入在网页API HttpConfiguration定义的服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆