Search code examples
c#asp.net-coreinversion-of-controlautofac

Autofac RegisterInstance does not work as expected


In my ASP.NET Core application there is a IMemoryCache registration as an instance in startup. When IMemoryCache is injected into a controller, the controller receives a different instance of memory cache than registered. How is this possible when IMemoryCache was registered as an instance?

Program.cs:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args)
            .Build()
            .Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureServices(s => s.AddAutofac())
            .UseStartup<Startup>();
}

Startup.cs:

public class Startup
{
    public static IMemoryCache MemoryCacheInstance;

    public Startup()
    {
    }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        MemoryCacheInstance = new MemoryCache(new MemoryCacheOptions());

        var builder = new ContainerBuilder();
        builder.RegisterInstance<IMemoryCache>(MemoryCacheInstance);
        builder.Populate(services);

        return new AutofacServiceProvider(builder.Build());
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

}

Controller:

public class UtilsController : Controller
{
    public UtilsController(IMemoryCache memoryCache)
    {
        if (Startup.MemoryCacheInstance == memoryCache)
        {
            // the debugger never gets here
        }
    }

    [HttpGet("api/utils/test-method")]
    public string TestMethod()
    {
        return null;
    }
}

Solution

  • You need to fix the order of registration. It seems that services already has a registered IMemoryCache so builder.Populate(services); will override the one you have created. Try:

    builder.Populate(services);
    builder.RegisterInstance<IMemoryCache>(MemoryCacheInstance);