I am using the Castle logging facility with log4net in my application (MVC3 web app). However, rather than using the ILogger interface directly I have abstracted this by creating another interface (IAuditor) with a concrete implementation Log4NetAuditor (see code below).
You may ask why I've done this since the point of ILogger is to abstract the underlying logging implementation. I've done because of strict observation of the onion architecture principle of abstracting all infrastructure concerns.
Now, this works just fine except all loggers are named the same: MyProject.Infrastructure.Log4NetAuditor:
2011-01-24 13:26:11,746 [11] DEBUG MyProject.Infrastructure.Log4NetAuditor [] - Attempting login...
2011-01-24 13:26:11,845 [11] DEBUG MyProject.Infrastructure.Log4NetAuditor [] - Authentication result is Authenticated
The IAuditor is exposed as a property on an AuditableComponent which is an abstract class from which all components that require logging derive.
public abstract class AuditableComponent
{
private IAuditor _auditor = NullAuditor.Instance;
public IAuditor Auditor
{
get { return _auditor; }
set { _auditor = value; }
}
//....
}
The Log4NetAuditor class looks like this:
public class Log4NetAuditor : IAuditor
{
private ILogger _logger = NullLogger.Instance;
public ILogger Logger
{
get { return _logger; }
set { _logger = value; }
}
public void Trace(string message)
{
_logger.Debug(message);
}
}
Now, it's clear why all log statements have the same logger name: ILogger is injected on the Log4NetAuditor class.
How, then, can I ensure the name of the logger corresponds to the name of the class that extends AuditableComponent?
I did the same thing as you but I also included a static LogManager class who's job it was to instantiate your logger. I made my constructors internal on the Logger class (your auditor class) so that they could not be created directly. This means that any external entity would need to get their reference through the LogManager class.
Now those types will be able to instantiate your Auditor with their own type being passed to the Create method.
UPDATE --
I used the Unity container to inject dependencies into this code as well. The relevant bits is the InjectionFactory. It allows me to specify a static method locally to inject a type based on some conditions.
Well, that does it for me at least!