使用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
是一个内部类。
看起来我可以这样做,但它没有给我需要这种注入类型的类的类型信息:
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>();
答案 0 :(得分:1)
您需要的是基于“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
注册具有不同的范围,例如单一范围,则会发生这种情况。