如何在激活时获取激活对象已注入的实例?

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

我正在尝试利用 Ninject 来帮助我建立一个可能的服务树 classes。我想使用 InCallScope 注入一个 ILogger 实例,这样任何子服务 class 都会使用相同的记录器。

记录器实现有一个名为 RootService 的 属性,它将指向使用记录器的最上层服务 class 实例。在根据它来自哪个服务 class 对记录的事件进行分类时,我会使用它的信息(子 classes 不会定义另一个 "log scope",因此我使用 InCallScope ).

我能否微调 ILogger Ninject 绑定,以便在 ILogger 实例激活时我可以有某种回调,我也有实例,它最近被注入其中?这样我就可以设置记录器的 RootService 属性。

有一个 OnActivation 绑定扩展,它是在实例化 ILogger 时执行的回调。 所以你可以这样做:

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

但是,IContext 不提供对 "parent" 实例的访问,因此您只能访问它注入的类型,而不能访问实例。

此外,如果这就足够了,则无需实际使用 OnActivation 扩展,您应该也可以这样做:

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 Service
{
    public Logger Logger { get; private set; }

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