Casey Charlton wrote a good post about logging with Castle Windsor, the logging facility and log4net. I've been tinkertankering around with Ninject so I decided to see if I could get it working as nicely.
Ivan Carrero wrote about a few posts about logging with Ninject, but newerish Ninject 1.0 features have enabled us to write code more like Casey's:
public class Service : IService { private ILogger logger; [Inject] public ILogger Logger { get { if (logger == null) logger = NullLogger.Instance; return logger; } set { logger = value; } } public void SomeLogic() { Logger.Info("some logic performed"); } }
Ninject integrates very nicely with Log4net and NLog by providing modules suited for their use, and the Ninject.Core.Logging namespace contains ILogger and some other stuff. Configure log4net, add the modules to the Ninject kernel and off you go.
var module = new InlineModule(m => m.Bind<IService>().To<Service>()); using (var kernel = new StandardKernel(module, new Log4netModule())) { var mine = kernel.Get<IService>(); mine.SomeLogic(); }
outputs a nice log message:
2008-06-20 12:32:31,759 [TestRunnerThread] INFO Example.Service - some logic performed
You don't have to use that Inject attribute in order to take advantage of Ninject's services. I don't like these guys on my code unless I have a better reason than supporting some tool. I think it's mostly a personal preference, but I've found myself embroiled in a constant struggle to be flexible, so it just works for me to get rid of any artifacts that could require later attention in my situation. Anyway, I wanted to get this example working just like Casey's. And to do this with Ninject, you have to use the auto-wiring extension.
One problem is that AutoWiringModule attempts to inject and execute every method, so I had to customize it a little to use the StandardMethodHeuristic instead of the auto-wiring one. This was very easy and is a good example of how Ninject is easily customized.
Another problem (which I submitted as an issue to the Ninject JIRA), is that the Log4NetModule doesn't bind ILogger to Log4NetLogger - so when the AutoWirer scans the Service class it won't inject the Logger property.
That's fixed pretty easily as well, and the code for both modifications and the new client code is below:
public class Modules { public static IModule AutoWiringStandardMethod = new AutoWiringStandardMethodModule(); public static IModule Default = new InlineModule(m => m.Bind<IService>().To<Service>()); public static IModule Logging = new LoggingModule(); } public class AutoWiringStandardMethodModule : StandardModule { public override void BeforeLoad() { Kernel.Components.Connect<IConstructorHeuristic>(new AutoWiringConstructorHeuristic()); Kernel.Components.Connect<IPropertyHeuristic>(new AutoWiringPropertyHeuristic()); Kernel.Components.Connect<IMethodHeuristic>(new StandardMethodHeuristic()); Kernel.Components.Connect<IFieldHeuristic>(new AutoWiringFieldHeuristic()); } public override void Load() {} } public class LoggingModule : StandardModule { public override void BeforeLoad() { Kernel.Components.Connect<ILoggerFactory>(new Log4netLoggerFactory()); } public override void Load() { Bind<ILogger>().To<Log4netLogger>(); } }
using (var kernel = new StandardKernel( Modules.Default, Modules.AutoWiringStandardMethod, Modules.Logging)) { var mine = kernel.Get<IService>(); mine.SomeLogic(); }
My feelings about Ninject are really positive. It's a pleasure to work with it and a masterfully branded open source project that has serious potential to overtake the big names in .NET dependency injection. I particularly abhor XML configuration and Ninject has a really comfortable API that lets me skate that. 1.0 just came out!
2 Responses
Reflective Perspective - Chris Alcock » The Morning Brew #120
23|Jun|2008 1[...] Logging with Ninject - Matt Hinze looks at using NInject 1.0's logging integration with Log4Net, in response to the posts that Casey Charlton has been making about Castle Windsor and Log4Net. [...]
Nate Kohari
25|Jun|2008 2Cool idea with the Modules static class, that can clean up the kernel definition pretty nicely. I also like your idea of changing how the AutoWiringExtension works. I think I'm going to either get rid of the AutoWiringMethodHeuristic or provide switches to enable/disable the different types of injection.
Thanks for your praise for Ninject, it's great to see the fun stuff people are doing with it now!
Leave a reply