在 Autofac 的 lambda 注册期间访问上下文信息?

Accessing contextual information during lambda registration in Autofac?

使用 Ninject 我可以做这样的事情:

Bind<ILogger>().ToMethod(context =>
{
    // Get type info
    var type = context.Request.Target.Member.DeclaringType;
    var logger = new ConcreteLogger(type);

    Kernel.Get<IFoo>().DoFoo(logger);
    return logger;
});

如何使用 Autofac 执行此操作?

这是我的代码:

 builder.Register(context => {
      var type = ?????
      var logger = new ConcreteLogger(type);

      context.Resolve<IFoo>().DoSomething(logger);
      return logger;
 }).As<ILogger>();

我可以在调试器中看到 context 实际上是 Autofac.Core.Resolving.InstanceLookup 类型,它有一个成员 ComponentRegistration.Target 但我无法访问它,因为 InstanceLookup 是一个内部class.

看来我可以做到这一点,但它没有给我需要此注入类型的 class 的类型信息:

 builder.Register(context => {
     var lookup = c as IInstanceLookup;
     var target = lookup.ComponentRegistration.Target as ComponentRegistration;
     var logger = new ConcreteLogger(target.Activator.LimitType);

      context.Resolve<IFoo>().DoSomething(logger);
      return logger;
 }).As<ILogger>();

你需要的是在"parent"组件的基础上注入一个组件。使用 Autofac,您注册组件,而这些组件并不知道谁需要它们。

顺便说一下,您可以通过实施自定义 模块 来做您想做的事。例子:

public class TestModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry componentRegistry,
        IComponentRegistration registration)
    {
        registration.Preparing += (sender, e) =>
        {
            Parameter parameter = new ResolvedParameter(
                (pi, c) =>
                {
                    return pi.ParameterType == typeof(ILogger);
                }, (pi, c) =>
                {
                    var p = new TypedParameter(typeof(Type), 
                                               e.Component.Activator.LimitType);
                    return c.Resolve<ILogger>(p);
                });

            e.Parameters = e.Parameters.Union(new Parameter[] { parameter });
        };
        base.AttachToComponentRegistration(componentRegistry, registration);
    }
}

并像这样注册模块:

builder.RegisterModule<TestModule>();

这样,每次解析一个组件时,它都会添加一个新参数,知道正在构造的类型以创建 ILogger 依赖项。

请注意,通过这样做,您可能拥有 captive dependency:为组件构建但用于另一个组件的依赖项。如果您的 ILogger 注册具有不同的范围,例如单例范围,就会发生这种情况。