Autofac scope lifetime issue

懵懂的女人 提交于 2019-12-05 12:02:18

you can try something like this:

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

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

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!

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