Search code examples
autofacdispose

How do I register a dependency in Autofac within the scope of an outer component while retaining Dispose support?


I have non-disposable class ReadModelRepository that depends on (but does not own) an instance of the disposable class ReadModelDbContext. Within a Module, I want to configure my Autofac 3.0.2 container so that ReadModelDbContext is resolved (one instance per dependency) only when ReadModelRepository objects are created.

This is what I currently have:

builder.RegisterType<ReadModelRepository>().As<IReadModelRepository>();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).AsSelf();

However, I do not want any arbitrary class to be able to resolve ReadModelDbContext using the registration provided by the module. Indeed, it's probable that other classes will need to resolve different ReadModelDbContext instances.

To solve this, I could use WithParameter, as in this snippet:

builder
    .RegisterType<ReadModelRepository> ().As<IReadModelRepository> ()
    .WithParameter (
        (p, c) => p.ParameterType == typeof (ReadModelDbContext), 
        (p, c) => new ReadModelDbContext (_connectionStringName));

However, I also need Autofac to automatically dispose the ReadModelDbContext when the lifetime scope resolving the ReadModelRepository (or actually that of its resolving component) ends. Using WithParameter, this doesn't seem to work.

So, in essence, I'd like to register a dependency only in the context of an outer component, with Dispose being called when the lifetime scope of the outermost component ends. Is this possible?


Solution

  • After some time, I've actually adopted a different approach: I register the inner component (ReadModelDbContext) with a private key:

    var privateKey = new object();
    builder.Register(c => new ReadModelDbContext(_connectionStringName)).Keyed<ReadModelDbContext>(privateKey);
    builder.Register(ctx => new ReadModelRepository(ctx.ResolveKeyed<ReadModelDbContext>(privateKey))).As<IReadModelRepository>();
    

    Since nobody else has the key, this effectively makes the ReadModelDbContext registration private to the ReadModelRepository.