Dependency injection and logging interfaces

dependency-injectionlogging

I was wondering what some of the best practices were around logging and logging frameworks and dependency injection. Specifically, if I am designing a class that needs a way to log, how should I go about getting an interface to log to keeping dependency injection in mind?

Dependency injection seems to state that external dependencies should be injected from the outside (constructor or property setters), so should I take an ILog instance in the constructor and use in the class? Should I consider logging an optional dependency and get it in a setter? Am I pushing for too much flexibility by allowing for the logging interface to change and should I just take a hard dependency on a specific logging interface (by e.g. create a static ILog variable via a call to a factory method)? Could this factory method call into the container to get the ILog implementation or will this create initialization conflicts between static variables being initialization and the IoC container being initialized?

Should I be doing this:

public class MyService : ISomeService
{
  private static readonly ILogger s_log = 
            LoggingFactory.GetLogger(typeof(MyService))
  ...
}

or perhaps this:

public class MyService : ISomeService
{
  protected virtual ILogger Logger {get; private set;}
  public MyService(ILogger logger, [other dependencies])
  {
    Logger = logger;
  }
}

or even this:

public class MyService : ISomeService
{
  public virtual ILogger Logger {get; set;}
  public MyService()
  {
  }
}

Other patterns or ways to do this? What are people out there doing? What's working and when?

Best Answer

It's great that you're looking into inversion-of-control and dependency-injection.

But for your question, there's another concept you might want to look into: aspect-oriented programming.

In .NET, there are some good frameworks available for doing aspect-oriented programming, including Castle, LinFu, and Microsoft's Policy-Injection Application Block. In fact, some inversion-of-control containers have some aspect-oriented features in them as well.

These concepts and tools help make concerns such as logging take a background seat in terms of code noise, and make be handled automagically.