我有ASP.NET MVC应用程序,我在其中注册了一个InstancePerHttpRequest
范围的组件。
builder.RegisterType<Adapter>().As<IAdapter>().InstancePerHttpRequest();
然后我有一段异步代码,我正在解析Adapter组件。
以下代码已简化
Task<HttpResponseMessage> t = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>
// IHandleCommand<T> takes an IAdapter as contructor argument
var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
);
上面的代码抛出异常:The request lifetime scope cannot be created because the HttpContext is not available.
所以我对这个问题进行了一些研究并找到了答案 https://stackoverflow.com/a/8663021/1003222
然后我将解析代码调整为此
using (var c= AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope(x => x.RegisterType<DataAccessAdapter>().As<IDataAccessAdapter>).InstancePerLifetimeScope()))
{
var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}
但例外保持不变。 The request lifetime scope cannot be created because the HttpContext is not available.
我错过了什么吗?
答案 0 :(得分:4)
using (var c= AutofacDependencyResolver.Current
.ApplicationContainer
.BeginLifetimeScope("AutofacWebRequest"))
{
var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}
答案 1 :(得分:2)
Autofac尝试从MVC依赖关系解析器解析容器, 如果您有异步操作,httpContext将不可用,因此DependencyResolver也不可用。
使容器在静态变量或适当的实例中可用的一个选项,并为此操作创建上下文范围。
public static IContainer Container
完成构建器设置后,复制容器
public class ContainerConfig
{
public static IContainer Container;
public static void RegisterComponents()
{
var builder = new ContainerBuilder();
builder.RegisterInstance(new Svc()).As<ISvc>();
Container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(Container ));
}
}
然后在解析时使用静态容器配置来创建你需要的实例。
using (var scope = ContainerConfig.Container.BeginLifetimeScope())
{
result = ContainerConfig.Container.Resolve<T>();
}
希望有所帮助
答案 2 :(得分:1)
如果您无权访问System.Web.Http,则无法使用DependencyResolver.Current。您需要存储容器并从中解析依赖关系:
//On Startup Class
public static IContainer Container { get; private set; }
public void Configuration(IAppBuilder app)
{
...
var builder = new ContainerBuilder();
builder.RegisterModule([yourmodules]);
...
var container = builder.Build();
Container = container;
}
然后,当您需要实例时:
using (var scope = Container.BeginLifetimeScope())
{
YourInterfaceImpl client = Container.Resolve<YourInterface>();
...
}
希望这有帮助!
答案 3 :(得分:1)
就我而言,我正在实例化WebAPI启动时的所有类型,以尽早发现任何故障。那时没有任何请求,因此使用注册为InstancePerRequest
的类型时出现此错误:
在请求实例的范围内,看不到标签匹配“ AutofacWebRequest”的范围。
基于@KozhevnikovDmitry的回答,这就是我如何使其工作的方式:
using (var scope = container.BeginLifetimeScope("AutofacWebRequest"))
{
foreach (Service item in container.ComponentRegistry.Registrations.SelectMany(x => x.Services))
{
Type type = item is TypedService ts ? ts.ServiceType
: item is KeyedService ks ? ks.ServiceType
: throw new Exception($"Unknown type `{item.Description}`");
try
{
scope.Resolve(type);
}
catch (Exception ex)
{
_log.Debug($"Error instantiating type `{type.FullName}`", ex);
throw;
}
}
}