Castle Windsor won't inject Logger in a property!
Asked Answered
A

3

6

I try to inject log4net in a ILogger property of my service class but the property is always NULL!

I've seen this topic but it doesn't help me!

How can I get Castle Windsor to automatically inject a property?

this is Program.cs

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

          );

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

I use log4net.config external file and this is my installer:

public class LoggerInstaller : IWindsorInstaller
{
    #region IWindsorInstaller Members

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

    #endregion
}

This is the class contains the property I want Windsor to inject:

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

Note that "eventService" and "Id" in the constructor are correctly injected! If I try to inject the Logger in the constructor it works and I've the Logger object: {log4net.Repository.Hierarchy.DefaultLoggerFactory+LoggerImpl}! :-(

I've tried to create a public property for EventService and Windsor can inject it properly! So I think the problem is related only to the ILogger interface.

I prepared a simple full-code example here:

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!");
    }
}
}

What's wrong?

Armidaarmiger answered 3/5, 2011 at 15:48 Comment(6)
Why don't you injeect the ILogger in the constructor?Hatshepsut
Following this best practice: castleproject.org/container/facilities/trunk/logging/index.html I want that Logger is optional and most important I want to know why it won't inject it in a property!Armidaarmiger
Are you installing the installer into the container? Are you resolving the FrmStart from the container?Jacqui
Yes! I edited the main post with the Install code.Armidaarmiger
Any luck on this? I am having the same issue. No deal breaker just curious...Hoplite
Updated link to the best practice is hereCastellatus
T
14

A problem is where you are checking it:

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

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

The property injection will not happen until after the constructor is run, so checking the property value in the constructor will never show the value you are expecting

Tympan answered 19/5, 2011 at 22:18 Comment(0)
B
1

I was having the same problem. It was always null.

I managed to solve the problem by injecting the logger in the constructor this way:

public ILogger logger;

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

    logger.Info("Something");
}
Blowfly answered 29/7, 2012 at 3:57 Comment(1)
I just ran into the same issue, property injection is always null but constructor injector works fine... My one application uses property injection of ILogger with no issues and the other does not work; both applications are using ABP and castle logging with log4net - I just cant figure this out...Stradivarius
I
0

You could also initialize your Logger by using:

public ILogger Logger { get; set; }

public MyController()
{
     Logger = NullLogger.Instance;
}
Inadmissible answered 10/1, 2017 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.