简体   繁体   English

如何解决 Autofac InstancePerHttpRequest

[英]How to resolve Autofac InstancePerHttpRequest

I have registered a component like this in my Global.asax.cs:我在我的 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 class: WebWorkContext class:

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

IWorkContext interface: IWorkContext接口:

public interface IWorkContext
{
     // Left out other code
}

The error that I am getting is:我得到的错误是:

No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested.从请求实例的 scope 中看不到标签匹配“httpRequest”的 scope。 This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.这通常表示注册为每个 HTTP 请求的组件正在被 SingleInstance() 组件(或类似场景)请求。在 web 集成下,始终从 DependencyResolver.Current 或 ILifetimeScopeProvider.RequestLifetime 请求依赖项,从不从容器本身请求依赖项.

How do I get this to work?我如何让它工作? This reason why I want it this way is because the work context handles stuff like getting the current customer etc.我之所以想要这种方式,是因为工作上下文处理诸如获取当前客户等内容。

Some more questions.还有一些问题。 Is it wise/best practices to register every at once?一次注册每个人是否明智/最佳做法? Will the be scenarios that I will need to add more components at another stage?我是否需要在另一个阶段添加更多组件?

Registrations that are marked with InstancePerHttpRequest are expected to be resolved from a particular nested lifetime scope that is created and disposed during each HTTP request.标有InstancePerHttpRequest的注册预计将从特定的嵌套生命周期 scope 解析,该生命周期在每个 HTTP 请求期间创建和处理。

If you add IWorkContext as a constructor parameter to one of your controllers you will find that an instance is injected.如果您将IWorkContext作为构造函数参数添加到您的控制器之一,您会发现注入了一个实例。 In your code you are attempting to resolve your service from the root lifetime scope and not the nested "per request" lifetime scope.在您的代码中,您试图从根生命周期 scope 而非嵌套的“每个请求”生命周期 scope 解析您的服务。

If you want to test resolving the service without running up your application you will need to create a lifetime scope with the same tag as the one created during the HTTP request.如果您想在不运行您的应用程序的情况下测试解析服务,您将需要创建一个生命周期 scope,其标签与在 HTTP 请求期间创建的标签相同。 In the MVC 3 integration the lifetime scope is tagged "httpRequest".在 MVC 3 集成中,生命周期 scope 被标记为“httpRequest”。

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

I think I will update the MVC integration to expose the "httpRequest" tag name publicly through the API so that string values don't need to be hard coded.我想我会更新 MVC 集成以通过 API 公开公开“httpRequest”标签名称,这样字符串值就不需要硬编码了。 It is also possible to pass your own ILifetimeScopeProvider implementation to the AutofacDependencyResolver so that you can control the creation of lifetime scopes outside of the ASP.NET runtime.也可以将您自己的ILifetimeScopeProvider实现传递给AutofacDependencyResolver ,以便您可以控制 ASP.NET 运行时之外的生命周期范围的创建。 This is useful in unit tests when there is no HTTP request available.当没有可用的 HTTP 请求时,这在单元测试中很有用。

I'm doing this in WebForms:我在 WebForms 中这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM