I wonder if this is something very simple that I'm just missing, or if there's a lot more to this.
Basically, what I'm trying to do is use StructureMap's setter injection for a logger implementation. The constructor for the logger that I wish for StructureMap to use accepts a Type
parameter for creating the logger:
public class Logger : ILogger
{
private ILog _log = null;
public Logger() { _log = LogManager.GetCurrentClassLogger(); }
public Logger(string name) { _log = LogManager.GetLogger(name); }
public Logger(Type loggerType) { _log = LogManager.GetLogger(loggerType); }
// The rest of the implementation...
}
In my bootstrapping code, I initialize it as thus:
ObjectFactory.Conf开发者_如何学Cigure(x => {
x.FillAllPropertiesOfType<ILogger>().Use(l =>
new Logger(l.BuildStack.Current.ConcreteType));
// Further unrelated bootstrapping...
});
It's not quite working 100%, and it's probably just a lack of full understanding on my part. So I have a few questions regarding the behavior I'm seeing:
- The "type" that the logger is seeing, when I step through the debugger and drill down into the log4net implementation, is of
ILogger
. How can I get it to be of the type which contains the setter being injected? - Only setters on StructureMap-built instances are being set. For example, on the repository interfaces/implementations for a data access layer. Other objects, such as my business models, aren't built from the StructureMap graph and are just instantiated as normal. Is there a way to tell StructureMap to also inject into those? I imagine there isn't, because how would it know? So then how can I resolve an instance of a properly constructed logger for the type? (I know how to call the resolver, which I do through a service locator, just not how to call it for this specific need.)
- It occurs to me that this "just doesn't feel right." Maybe I'm missing something about named instances? Because if the bootstrapper manages to graph an implementation of this, how/when then would it supply different instances for each class that has the setter?
Maybe there's an entirely different/simpler/better way to accomplish what I'm trying to do, and I welcome suggestions for that. Basically, I'm abstracting my logging implementation behind an IoC container, and I need class-specific loggers.
Perhaps this is not the exact answer you are looking for, but why not simplify everything by creating an ILoggerFactory
? Instead of registering the ILogger
, you can register a ILoggerFactory
and inject the ILoggerFactory
in your classes:
public interface ILoggerFactory
{
ILogger CreateFor(string name);
ILogger CreateFor<T>();
ILogger CreateFor(Type loggerType);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger CreateFor(string name)
{
return LogManager.GetLogger(name);
}
public ILogger CreateFor<T>()
{
return CreateFor(typeof(T));
}
public ILogger CreateFor(Type loggerType)
{
return LogManager.GetLogger(loggerType);
}
}
精彩评论