Castle Windsor IoC不会将log4net注入我的控制器

时间:2013-05-12 21:15:47

标签: .net asp.net-mvc-4 inversion-of-control log4net castle-windsor

我正在使用Castle Windsor中的这个(http://docs.castleproject.org/Windsor.Windsor-Tutorial-Part-Five-Adding-logging-support.ashx)IoC教程,我已经通过了所有前面的步骤,如上所述,我试图通过属性将log4net记录器注入我的控制器,如下:

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();
    }

}

但遗憾的是在执行Logger.Debug时,Logger为null,因此结果为null引用异常。虽然我正打算打电话

var logger = container.Resolve<ILogger>();

logger.Debug("Container bootstrapped");

在Global.asax记录器中完全解析。

为什么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());
        }
    }
}

1 个答案:

答案 0 :(得分:3)

这不是你问题的真正答案,而是一些建议:

1)在记录时使用空对象模式来阻止NRE

ILogger logger = NullLogger.Instance;
public ILogger Log
{
    get { return logger; }
    set { logger = value ?? NullLogger.Instance; }
}

2)在大多数情况下,应首先添加记录工具 - 在任何安装人员注册之前:

container = new WindsorContainer();
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
container.Install(FromAssembly.This());

如果您稍后添加日志记录工具,则可能会在安装过程中丢失一些有价值的消息。