5

我有 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.

我错过了什么吗?

4

4 回答 4

4

你可以尝试这样的事情:

using (var c= AutofacDependencyResolver.Current
                                       .ApplicationContainer
                                       .BeginLifetimeScope("AutofacWebRequest"))
{
   var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}
于 2013-08-16T00:38:16.580 回答
4

Autofac 尝试从 MVC Dependency Resolver 解析容器,如果您有异步操作,则 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>();
}

希望能帮助到你

于 2015-02-14T01:06:52.873 回答
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>();
   ...
}

希望这有帮助!

于 2016-09-23T12:25:54.387 回答
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;
        }
    }
}
于 2019-02-13T15:19:30.043 回答