I have the following interface:
public interface ILogger
{
void Debug(string message, params object[] values);
void Info(string message, params objec
We use a similar ILogger wrapper around log4net and typically use constructor injection. We use an interceptor as a factory method responsible for creating the Logger. Here is our typical registry for logging setup.
public class CommonsRegistry : Registry
{
public CommonsRegistry()
{
For<ILogger>()
.AlwaysUnique()
.TheDefault.Is.ConstructedBy(s =>
{
if (s.ParentType == null)
return new Log4NetLogger(s.BuildStack.Current.ConcreteType);
return new Log4NetLogger(s.ParentType);
});
var applicationPath = Path.GetDirectoryName(Assembly.GetAssembly(GetType()).Location);
var configFile = new FileInfo(Path.Combine(applicationPath, "log4net.config"));
XmlConfigurator.ConfigureAndWatch(configFile);
}
}
The parent type null check is necessary when there are dependencies on concrete types.
The rest is optional log4net setup stuff.
One thing I do like about this setup is the ability to use a null loggers for unit testing.
If the type parameter is context-specific, I don't think this is going to work as shown. If you need to pass something context specific in the constructor, you are likely going to have to create a factory interface and implementation that returns an instance of the ILogger:
public interface ILoggerFactory
{
ILogger Create(Type type);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger Create(Type type)
{
return new Log4netLogger(type);
}
}
It might be possible to bootstrap StructureMap to supply the instance you want based on the type, but that assumes a limited number of types that you know in advance.
I really need to get out of the habit of answering my own question, but for those who run across it, here's the answer.
return ObjectFactory.With(type).GetInstance<T>();
I actually have a wrapper to structuremap (to avoid exposing the structuremap dependency to my app) that looks like the following:
public static class ServiceManager
{
public static T Get<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static T Get<T>(Type type)
{
return ObjectFactory.With(type).GetInstance<T>();
}
}
Any time in the code I need a logger, I call the following:
ServiceManager.Get<ILogger>(GetType()).Info("Logging page view...");