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?

Community
  • 1
  • 1
danyolgiax
  • 12,798
  • 10
  • 65
  • 116

3 Answers3

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

Philip Rieck
  • 32,368
  • 11
  • 87
  • 99
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");
}
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 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... – Ivan Sager Apr 02 '20 at 00:30
0

You could also initialize your Logger by using:

public ILogger Logger { get; set; }

public MyController()
{
     Logger = NullLogger.Instance;
}
Liviu H.
  • 9
  • 1