2

我正在研究这个(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 的执行点Logger.Debug为空,因此导致空引用异常。虽然当我试图打电话时

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

logger.Debug("Container bootstrapped");

Global.asax 记录器内部已完美解决。

为什么 Windsor 不想解决控制器内部的依赖关系?


编辑

控制器是通过 Windsor 创建的

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

控制器工厂.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);
        }
    }
}

控制器安装程序.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());
        }
    }
}
4

1 回答 1

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

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

于 2013-05-14T15:26:47.093 回答