I wanted to inject a logger to my controllers and I needed to pass extended info to the logger's constructor. For the purpose I've use RegisterWithContext
:
container.RegisterWithContext<Common.Logging.ILogger>(context =>
{
if (context.ServiceType == null && !container.IsVerifying())
{
throw new InvalidOperationException(
"Can't request ILogger directly from container, " +
"it must be injected as a dependency.");
}
return new Common.Logging.NLogLogger(context.ImplementationType.FullName);
});
RegisterWithContext
extension method explicitly registers the supplied delegate as Transient
.
I need to inject the same Logger (Common.Logging.NLogLogger
) in a service which happens to be singleton.
Before upgrading to SimpleInjector 3.0.6 things seemed to work as expected and container.Verify()
was quite happy with the whole configuration.
After the upgrade the verifier returns a few errors:
[Lifestyle Mismatch] SearchEngineIndexerService (Singleton) depends on ILogger (Transient). [Lifestyle Mismatch] MembershipService (Web Request) depends on ILogger (Transient).
and it makes sense. I can understand why that happens and why it should be avoided.
I am trying to avoid the "Do I log too much" syndrome but, actually, I really need to do some logging in a couple of services.
I've tried to use RegisterConditional to register a different logger based on certain conditions but, of course, all the logger now should be registered conditional or I get this exception:
Type ILogger has already been registered as unconditional registration. For non-generic types, conditional and unconditional registrations can't be mixed.
What's the best approach to register a logger as transient for a controller and another one for a singleton service?
The reason you are seeing this exception now, is because v3.0.6 fixed some bugs that prevented the lifestyle mismatch warning from showing up in certain occasions.
It is best to ignore the
RegisterWithContext
extension method, because it has been superseded by theRegisterConditional
method in v3.RegisterConditional
however, only allows registering types; not delegates, because delegates allow you to make decisions based on runtime decisions, but it is bad practice to make runtime decisions during object graph resolution.So instead, it is best to define a proxy logger class that allows forwarding the call to the real logger. For instance:
This implementation can be registered as follows:
The documentation describes this in more detail.