raine
raine

Reputation: 857

Managing Lifetime Scopes with Autofac

Context: Owin (self-host) + WebApi + UseAutofacMiddleware + UseAutofacWebApi

What I'm trying to do is:

Register an ILog instance in the app startup container.

For each request, register a new ILog instance wrapping the "root" instance, so that each middleware and/or per-request services can use it.

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterInstance(log).As<ILog>();
containerBuilder.Register(ctx => {
    var rootLog = ctx.Resolve<ILog>();
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

However, Autofac complains about circular dependencies when instancing middleware having an ILog in their constructors.

If I name the "root log", and resolve with the given name, everything works as expected.

containerBuilder.RegisterInstance(log)
                .Named("root", typeof(ILog));
containerBuilder.Register(ctx => {
    var rootLog = ctx.ResolveNamed<ILog>("root");
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

Am I forced to use a named instance to make it work?

Upvotes: 0

Views: 307

Answers (1)

Cyril Durand
Cyril Durand

Reputation: 16192

Autofac uses the latest registered service when a component request for a service.

In your case, the latest ILog registered is a lambda expression :

containerBuilder.Register(ctx => {
    var rootLog = ctx.Resolve<ILog>();
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

This lambda expression request an ILog which is what Autofac is trying to build : that's why it detects a circular dependency.

The easiest way to avoid the circular dependency is to make your registration not rely on itself. This is what you do by resolving a named ILog and this is the solution I recommend.

In your case, you can also directly use the root log without resolving it :

containerBuilder.RegisterInstance(rootLog).As<ILog>();
containerBuilder.Register(ctx => {
    return new PrependStringLog(rootLog, "request: ");
}).InstancePerRequest();

Upvotes: 1

Related Questions