如何解决Autofac InstancePerHttpRequest

时间:2012-04-05 11:00:50

标签: c# asp.net-mvc-3 dependency-injection autofac

我在Global.asax.cs中注册了这样的组件:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());

builder.RegisterType<WebWorkContext>().As<IWorkContext>().InstancePerHttpRequest();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

// This is where my error happens, not sure why?
var workContext = container.Resolve<IWorkContext>();

WebWorkContext上课:

public class WebWorkContext : IWorkContext
{
     // Left out other code
}

IWorkContext界面:

public interface IWorkContext
{
     // Left out other code
}

我得到的错误是:

  

从请求实例的作用域中看不到具有匹配'httpRequest'的标记的作用域。这通常表示注册为每HTTP请求的组件正被SingleInstance()组件(或类似场景)重新请求。在Web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,从不从容器本身请求

我如何让它工作?这就是为什么我这样想是因为工作上下文处理诸如获取当前客户等的东西。

还有一些问题。一次注册是否明智/最佳做法?我需要在另一个阶段添加更多组件吗?

2 个答案:

答案 0 :(得分:22)

标记为InstancePerHttpRequest的注册应该从每个HTTP请求期间创建和处置的特定嵌套生命周期范围中解析。

如果将IWorkContext作为构造函数参数添加到其中一个控制器,您会发现注入了一个实例。在您的代码中,您尝试从根生命周期范围而不是嵌套的“每个请求”生命周期范围中解析您的服务。

如果要在不运行应用程序的情况下测试解析服务,则需要使用与HTTP请求期间创建的标记相同的标记创建生命周期范围。在MVC 3集成中,生命周期范围被标记为“httpRequest”。

using (var httpRequestScope = container.BeginLifetimeScope("httpRequest"))
{
    Assert.That(httpRequestScope.Resolve<IWorkContext>(), Is.Not.Null);
}

我想我会更新MVC集成以通过API公开公开“httpRequest”标记名称,以便字符串值不需要硬编码。也可以将您自己的ILifetimeScopeProvider实现传递给AutofacDependencyResolver,以便您可以控制在ASP.NET运行时之外创建生命周期范围。当没有可用的HTTP请求时,这在单元测试中很有用。

答案 1 :(得分:2)

我在WebForms中这样做:

this.RoutingService = ((Global)HttpContext.Current.ApplicationInstance).ContainerProvider.RequestLifetime.Resolve<RoutingService>();