Lu4
Lu4

Reputation: 15032

Castle Windsor IoC doesn't inject log4net into my controller

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

Answers (1)

Aleš Roub&#237;ček
Aleš Roub&#237;ček

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

Related Questions