dependency-injectionautofacasp.net-core-3.1service-locator

ServiceLocator with Autofac in asp.net core 3.1


I'm developing an asp.net core 3.1 webapi application and i'm using Autofac as DI container. For one particular case i cannot use ConstructorInjection nor propertyinjection nor methodinjection. My only way is to implement a sort of ServiceLocator pattern with the support of Autofac.

*I known that the service locator is an antipattern, but i will use that only if it will be the only chance *

Said that, I create a little static class :

public static class ServiceLocator
{

    private static XXXX Resolver;

    public static T Resolve<T>()
    {
        return Resolver.Resolve<T>();
    }

    public static void SetCurrentResolver(XXXX resolver)
    {
        Resolver = resolver;
    }
}

I write XXXX on the type of Resolver property because i don't know which is the Autofac class to use. The method SetCurrentResolver will be called in the Configure method of Startup.cs

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILifetimeScope serviceProvider)
    {
        //OTHER STUFF NOT RELATED HERE

        ServiceLocator.SetCurrentResolver(serviceProvider);
    }

I tried to pass the instance of ILifetimeScope but when i use it later in the service locator it will be Disposed and then not work. I thinked to pass an IContainer object but i'm not able to retrieve an instance in Startup.cs (neither in the Configure method nor in the ConfigureContainer)

I Report the ConfigureContainer method for completion

    public void ConfigureContainer(ContainerBuilder builder)
    {
        //first register the dependency for WebApi Project

        builder.RegisterType<HttpContextUserService>().As<IUserService>().SingleInstance();

        //and then register the dependency for all other project

        var appConfiguration = new AppConfiguration();
        Configuration.GetSection("Application").Bind(appConfiguration);
        builder.RegisterInstance(appConfiguration).SingleInstance();

        builder.RegisterModule(new DependencyInjectionBootstrapper(appConfiguration)); 
        
    }

Anyone can help me with this problem?

Thanks


Solution

  • This is actually answered in the Autofac docs if you look at the example.

    Here are the relevant bits.

    public class Startup
    {
      public Startup(IHostingEnvironment env)
      {
        // Body omitted for brevity.
      }
    
      public ILifetimeScope AutofacContainer { get; private set; }
    
      public void ConfigureServices(IServiceCollection services)
      {
        // Body omitted for brevity.
      }
    
      public void ConfigureContainer(ContainerBuilder builder)
      {
        // Body omitted for brevity.
      }
    
      public void Configure(IApplicationBuilder app)
      {
        // If, for some reason, you need a reference to the built container, you
        // can use the convenience extension method GetAutofacRoot.
        // THIS IS WHERE YOU'D SET YOUR SERVICE LOCATOR.
        this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
      }
    }