Замок Виндзор не будет вводить Logger в собственность! - PullRequest
6 голосов
/ 03 мая 2011

Я пытаюсь внедрить log4net в свойство ILogger моего класса обслуживания, но свойство всегда NULL!

Я видел эту тему, но она мне не помогает!

Как заставить Castle Windsor автоматически вводить свойство?

это Program.cs

 CastleContainer.Instance
        .Install(
          new RepositoriesInstaller(),
          new PersistenceInstaller(),
          new LoggerInstaller(),
          new FormInstaller(),
          new ServiceInstaller()

          );

        FrmStart form1 = CastleContainer.Resolve<FrmStart>(new {Id="666" });

Я использую внешний файл log4net.config, и это мой установщик:

public class LoggerInstaller : IWindsorInstaller
{
    #region IWindsorInstaller Members

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
         container.AddFacility("logging", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
    }

    #endregion
}

Этот класс содержит свойство, которое я хочу добавить в Виндзор:

public partial class FrmStart : Form
{
    private EventService EventService;

    private ILogger logger = NullLogger.Instance;
    public ILogger Logger
    {
        get { return logger; }
        set { logger = value; }
    }

    public FrmStart(EventService eventService, string Id)
        : this()
    {

        Logger.Debug("xxx");

        this.EventService = eventService;
        this.id = Id;
    }

Обратите внимание, что "eventService" и "Id" в конструкторе введены правильно! Если я пытаюсь вставить Logger в конструктор, он работает, и у меня есть объект Logger: {Log4net.Repository.Hierarchy.DefaultLoggerFactory + LoggerImpl}! : - (

Я пытался создать публичное свойство для EventService, и Виндзор может его правильно внедрить! Поэтому я думаю, что проблема связана только с интерфейсом ILogger.

Я подготовил простой пример с полным кодом:

using Castle.Core.Logging;
using Castle.Facilities.Logging;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;

namespace IocTest
{


public class LoggerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
         container.AddFacility("logger", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
    }
}
public class LogicInstaller : IWindsorInstaller
{
     public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(AllTypes.FromThisAssembly()
                            .Pick()
                            .If(t => t.Name.StartsWith("Logic"))
                            .Configure((c => c.LifeStyle.Transient)));
    }
}

class Program
{
    static void Main(string[] args)
    {
        IWindsorContainer container = new WindsorContainer();

        container.Install(
        new LoggerInstaller(),
          new LogicInstaller()
          );


        LogicClass1 logic1 = container.Resolve<LogicClass1>();
        LogicClass2 logic2 = container.Resolve<LogicClass2>();
    }
}

public class LogicClass1
{
    private ILogger logger = NullLogger.Instance;
    public ILogger Logger
    {
        get { return logger; }
        set { logger = value; }
    }

    public LogicClass1()
    {
        logger.Debug("Here logger is NullLogger!");
    }
}

public class LogicClass2
{
    public LogicClass2(ILogger logger)
    {
        logger.Debug("Here logger is properly injected!");
    }
}
}

Что не так?

Ответы [ 3 ]

14 голосов
/ 20 мая 2011

Проблема в том, где вы проверяете это:

 public ILogger Logger
    {
        get { return logger; }
        set { logger = value; }
    }

    public LogicClass1()
    {
        logger.Debug("Here logger is NullLogger!");
    }

Внедрение свойства не произойдет до тех пор, пока после не будет запущен конструктор, поэтому проверка значения свойства в конструкторе никогда не покажет ожидаемое вами значение

1 голос
/ 29 июля 2012

У меня была такая же проблема. Это всегда было null.

Мне удалось решить проблему, введя регистратор в конструктор следующим образом:

public ILogger logger;

public MyController(ILogger logger)
{
    this.logger = logger;

    logger.Info("Something");
}
0 голосов
/ 10 января 2017

Вы также можете инициализировать свой регистратор, используя:

public ILogger Logger { get; set; }

public MyController()
{
     Logger = NullLogger.Instance;
}
...