Zoltán Tamási February 2016

How to get the instance into which the activated object has been injected at activation time?

I'm trying to utilize Ninject to help me build up a possible tree of service classes. I'd like to inject an ILogger instance using InCallScope so any child service class would use the same logger.

The logger implementation has a property called RootService, which would point to the upper-most service class instance which uses the logger. I would use information from it when categorizing logged events according to from which service class it has come from (child classes would not define another "log scope", hence I use InCallScope).

Can I fine-tune the ILogger Ninject binding so that I could have kind of a callback when the ILogger instance is activated, and I had there the instance too, into which it recently got injected? So there I could set the RootService property of my logger.

Answers


BatteryBackupUnit February 2016

There's is the OnActivation binding extension which is a callback which is executed when ILogger is instanciated. So you can do the following:

public class Test
{
    [Fact]
    public void Foo()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Service>().ToSelf();

        kernel.Bind<Logger>().ToSelf()
            .OnActivation((ctx, logger) =>
                logger.Initalize(ctx.Request.Target.Member.DeclaringType));

        var service = kernel.Get<Service>();

        service.Logger.RootService.Should().Be(typeof(Service));
    }
}

public class Logger
{
    public Type RootService { get; private set; }

    public void Initalize(Type rootService)
    {
        this.RootService = rootService;
    }
}

public class Service
{
    public Logger Logger { get; private set; }

    public Service(Logger logger)
    {
        Logger = logger;
    }
}

However, IContext does not provide access to the "parent" instance, so you can only access the type it's injected into, but not the instance.

Also, if that should be enough, there's no need to actually use the OnActivation extension, you should also be able to just do it like this:

public class Test
{
    [Fact]
    public void Foo()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Service>().ToSelf();

        kernel.Bind<Logger>().ToSelf()
            .WithConstructorArgument(
                typeof(Type),
                ctx => ctx.Request.Target.Member.DeclaringType);

        var service = kernel.Get<Service>();

        service.Logger.RootService.Should().Be(typeof(Service));
    }
}

public class Logger
{
    private readonly Type _rootService;

    public Logger(Type rootService)
    {
        _rootService = rootService;
    }

    public Type RootService
    {
        get { return _rootService; }
    }
}

public class Se 

Post Status

Asked in February 2016
Viewed 3,235 times
Voted 10
Answered 1 times

Search




Leave an answer