I have a LogManager class which has a type parameter to give to log4net like this:
public class LogManager<T> : ILogManager
{
private ILog Logger { get; set; }
public LogManager()
{
Logger = LogManager.GetLogger(typeof(T));
}
}
And I register this logger as conditional:
container.RegisterConditional(typeof(ILogManager),
c => typeof(LogManager<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Transient,
c => true);
It works like it supposed to, I inject the log manager to my controllers' constuctors and use it. But there is a problem. I have a lot of singleton classes that should use the log manager too, but I can't inject it to them because log manager has a shorter life then others, so Simple Injector won't allow me to do it.
The proposed solution is to inject a log factory class to the other singletons and call the factory every time which sounds like a bad idea. I don't want to do _logFactory.GetLogger().Debug("log") every time I want to log something. Or I am missing something about this solution?
The other proposed solution is to make singleton classes transient which doesn't make any sense.
Any suggestions how should I proceed? Is there anything wrong with my design?
You should make the registration singleton:
container.RegisterConditional(typeof(ILogManager),
c => typeof(LogManager<>).MakeGenericType(c.Consumer.ImplementationType),
Lifestyle.Singleton,
c => true);
Since LogManager<>
is a generic type, Simple Injector will create one instance per closed generic version. So LogManager<HomeController>
is a different instance than LogManager<UsersController>
. This is simply because there is no way to use the same instance (this is impossible in .NET). So each consumer will still have its own LogManager<T>
and with that its own log4net ILog
implementation. The loggers returned from log4net's LogManager.GetLogger
are thread-safe, and that's why its no problem to make your own LogManager<T>
singleton.