Reputation: 15032
I'm working out this(http://docs.castleproject.org/Windsor.Windsor-Tutorial-Part-Five-Adding-logging-support.ashx) IoC tutorial in Castle Windsor, I have passed all of the previous steps and as in above tutorial I'm trying to get the log4net logger injected into my controller via property, like following:
public class HomeController : Controller
{
// this is Castle.Core.Logging.ILogger, not log4net.Core.ILogger
public ILogger Logger { get; set; }
public ActionResult Index()
{
Logger.Debug("Hello world");
ViewBag.Message = "Hello world";
return View();
}
}
but unfortunately at point of execution of Logger.Debug
Logger is null, so that results with null reference exception. Though when I'm trying to call
var logger = container.Resolve<ILogger>();
logger.Debug("Container bootstrapped");
inside Global.asax logger is perfectly resolved.
Why does Windsor doesn't want to resolve dependency inside controller?
EDIT
Controller is created via Windsor
Global.asax
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Castle.Core.Logging;
using Castle.Windsor;
using Castle.Windsor.Installer;
using FlightManagementSystem.WebPlatform.Configuration.IoC.Windsor.Factories;
namespace FlightManagementSystem.WebPlatform
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
private static IWindsorContainer container;
protected void Application_Start()
{
Debugger.Break();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
container = new WindsorContainer();
container.Install(FromAssembly.This());
var controllerFactory = new ControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
protected void Application_End()
{
container.Dispose();
}
}
}
ControllerFactory.cs
using System;
using System.Web;
using System.Web.Mvc;
using Castle.MicroKernel;
namespace FlightManagementSystem.WebPlatform.Configuration.IoC.Windsor.Factories
{
public class ControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public ControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
public override void ReleaseController(IController controller)
{
kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, String.Format(Resources.THE_CONTROLLER_FOR_PATH_0_COULD_NOT_BE_FOUND, requestContext.HttpContext.Request.Path));
}
return (IController) kernel.Resolve(controllerType);
}
}
}
ControllerInstaller.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace FlightManagementSystem.WebPlatform.Configuration.IoC.Windsor.Installers
{
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register
(
Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient()
);
}
}
}
LoggerInstaller.cs
using Castle.Facilities.Logging;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace FlightManagementSystem.WebPlatform.Configuration.Logger.log4net
{
public class LoggerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
}
}
}
Upvotes: 2
Views: 1972
Reputation: 5187
It is not really answer to your problem, but a few suggestions:
1) Use null object patter to prevent NRE
when logging:
ILogger logger = NullLogger.Instance;
public ILogger Log
{
get { return logger; }
set { logger = value ?? NullLogger.Instance; }
}
2) Logging facility should be added in most cases at first - before any installers are registered:
container = new WindsorContainer();
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
container.Install(FromAssembly.This());
If you add logging facility later you can lost some valuable messages during installation.
Upvotes: 3