log4net with DI Simple Injector

There’s nothing special about Simple Injector when it comes to configuring log4net. For instance, you can register ILog as follows:

container.RegisterSingleton<ILog>(LogManager.GetLogger(typeof(object)));

Obviously this registered a single logger for the complete application. In case you want to inject a different logger per class, you will have to define your own adapter implementation:

public sealed class Log4NetAdapter<T> : LogImpl
{
    public Log4NetAdapter() : base(LogManager.GetLogger(typeof(T)).Logger) { }
}

You can register this adapter as follows:

container.RegisterConditional(typeof(ILog),
    c => typeof(Log4NetAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

This ensures that each consumer gets its own Log4NetAdapter<T> implementation.

Do note though that IMO it’s much better to prevent application code to take a dependency on 3rd party library abstractions. I think it’s much better to define you own logger abstraction.

My experience with log4net is that when log4net doesn’t log anything, there’s something wrong with your log4net configuration. What I hate about log4net is that it never throws any exceptions when you misconfigured it. It just swallows and continues, which makes working with log4net much more painful than it should be.

One thing that can help is hooking onto the LogLog.LogReceived event of log4net at startup. This allows you to check if there are any errors. For instance this is the code I used in a previous project:

LogLog.LogReceived += (s, e) =>
{
    if (e.LogLog.Prefix.Contains("ERROR"))
    {
        throw new ConfigurationErrorsException(e.LogLog.Message,
            e.LogLog.Exception);
    }
};

This makes sure your application directly stops with a clear exception when log4net is misconfigured.

Leave a Comment