我有ASP.NET MVC应用程序,我在其中注册了一个带有InstancePerHttpRequest
范围的组件。
builder.RegisterType<Adapter>().As<IAdapter>().InstancePerHttpRequest();
然后我有一个异步的代码片段,我正在解析适配器组件。
以下代码已简化
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.
我错过了什么吗?
你可以尝试这样的事情:
using (var c= AutofacDependencyResolver.Current
.ApplicationContainer
.BeginLifetimeScope("AutofacWebRequest"))
{
var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}
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>();
}
希望能帮助到你
如果您无权访问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>();
...
}
希望这有帮助!
在我的例子中,我在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;
}
}
}