14

我在 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”匹配的标记的范围。这通常表明注册为 per-HTTP 请求的组件正在被 SingleInstance() 组件(或类似场景)请求。在 Web 集成下,始终从 DependencyResolver.Current 或 ILifetimeScopeProvider.RequestLifetime 请求依赖项,而不是从容器本身.

我怎样才能让它工作?我之所以想要这种方式是因为工作上下文处理诸如获取当前客户之类的事情。

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

4

2 回答 2

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 请求时,这在单元测试中很有用。

于 2012-04-06T04:12:40.580 回答
2

我在 WebForms 中这样做:

this.RoutingService = ((Global)HttpContext.Current.ApplicationInstance).ContainerProvider.RequestLifetime.Resolve<RoutingService>();
于 2012-07-23T01:43:51.107 回答