在 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
注册具有不同的范围,例如单例范围,就会发生这种情况。
使用 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
注册具有不同的范围,例如单例范围,就会发生这种情况。