Reputation: 857
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
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