Autofac scope lifetime issue

六月ゝ 毕业季﹏ 提交于 2019-12-10 09:05:43

问题


I have ASP.NET MVC application where I registered a component with an InstancePerHttpRequest scope.

builder.RegisterType<Adapter>().As<IAdapter>().InstancePerHttpRequest();

then I have an async piece of code where I'm resolving the Adapter component.

The following code is simplified

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 code above is throwing an exception: The request lifetime scope cannot be created because the HttpContext is not available.

So I did some research on the subject and found this answer https://stackoverflow.com/a/8663021/1003222

Then I adjusted the resolving code to this

 using (var c= AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope(x => x.RegisterType<DataAccessAdapter>().As<IDataAccessAdapter>).InstancePerLifetimeScope()))
 {
       var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
 }

But the exception stayed the same. The request lifetime scope cannot be created because the HttpContext is not available.

Am I missing something ?


回答1:


you can try something like this:

using (var c= AutofacDependencyResolver.Current
                                       .ApplicationContainer
                                       .BeginLifetimeScope("AutofacWebRequest"))
{
   var h = DependencyResolver.Current.GetServices<IHandleCommand<T>>();
}



回答2:


Autofac tries to resolve the container from the MVC Dependency Resolver, If you have a async operation the httpContext won't be available so DependencyResolver won't be available either.

One option in to make the container available in a static variable or a proper instance, and create a context scope for this operation.

public static IContainer Container

once you have the builder setup, copy the 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 ));
    }
}    

then when resolving use the static container config to create the instance you need.

using (var scope = ContainerConfig.Container.BeginLifetimeScope())
{
       result = ContainerConfig.Container.Resolve<T>();
}

hope it helps




回答3:


If you do not have access to System.Web.Http you can´t use DependencyResolver.Current. You need to store your container and Resolve the dependency from it:

//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;
}

Then, when you need your instance:

using (var scope = Container.BeginLifetimeScope())
{                                
   YourInterfaceImpl client = Container.Resolve<YourInterface>();
   ...
}

Hope this help!




回答4:


In my case I was instantiating all types on WebAPI startup, to catch any failures as early as possible. At that point, there's no request, so with a type registered as InstancePerRequest I was getting this error:

No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.`

Based on @KozhevnikovDmitry's answer, this is how I got it working:

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;
        }
    }
}


来源:https://stackoverflow.com/questions/15050207/autofac-scope-lifetime-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!