C# – How to configure and enable log4net for a stand-alone class library assembly

clog4netnet

Background

I am writing a class library assembly in C# .NET 3.5 which is used for integration with other applications including third-party Commercial-Off-The-Shelf (COTS) tools. Therefore, sometimes this class library will be called by applications (EXEs) that I control while other times it will be called by other DLLs or applications that I do not control.

Assumptions

  • I am using C# 3.0, .NET 3.5 SP1, and Visual Studio 2008 SP1
  • I am using log4net 1.2.10.0 or greater

Constraints

Any solution must:

  • Allow for the class library to enable and configure logging via it's own configuration file, if the calling application does not configure log4net.
  • Allow for the class library to enable and configuring logging via the calling applications configuration, if it specifies log4net information

OR

  • Allow for the class library to enable and configuring logging using it's own configuration file at all times.

Problem

When my stand-alone class library is called by a DLL or application that I do not control (such as a third-party COTS tool) and which doesn't specify log4net configuration information, my class library is unable to do any of it's logging.


Question

How do you configure and enable log4net for a stand-alone class library assembly so that it will log regardless if the calling application provides log4net configuration?

Best Answer

You can probably code something around the XmlConfigurator class:

public static class MyLogManager
{
    // for illustration, you should configure this somewhere else...
    private static string configFile = @"path\to\log4net.config";

    public static ILog GetLogger(Type type)
    {
        if(log4net.LogManager.GetCurrentLoggers().Length == 0)
        {
            // load logger config with XmlConfigurator
            log4net.Config.XmlConfigurator.Configure(configFile);
        }
        return LogManager.GetLogger(type);
    }
}

Then in your classes, instead of:

private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

Use:

private static readonly ILog log = MyLogManager.GetLogger(typeof(MyApp));

Of course, it would be preferable to make this class a service and dynamically configure it with the IoC container of your choice, but you get the idea?

EDIT: Fixed Count() problem pointed out in comments.