在autofac中解析IEnumerable
时是否可以过滤依赖关系?
我有一个接口的多个实现(在下面的例子中为IHandler
),它们被定义为&在隔离项目中使用Autofac模块注册。我希望能够在解析父类型(下面的示例中为Processor
)时过滤实现。
IHandler
实现可以注入Processor
并在ctor
中过滤,但这需要解决所有实现,无论是否需要它们都是浪费。
public interface IHandler { }
public class Handler1 : IHandler { }
public class Handler2 : IHandler { }
public class Handler3 : IHandler { }
public class Processor {
public IEnumerable<IHandler> Handlers;
public Processor(IEnumerable<IHandler> handlers) {
Handlers = handlers;
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Handler1>().As<IHandler>();
builder.RegisterType<Handler2>().As<IHandler>();
builder.RegisterType<Handler3>().As<IHandler>();
builder.RegisterType<Processor>().AsSelf();
var container = builder.Build();
var processor = container.Resolve<Processor>();
}
由于一次只能解决1个密钥,因此使用密钥的尝试无效:
[Flags]
public enum HandlerType
{
One = 1,
Two = 2,
Three = 4
}
builder.RegisterType<Handler1>().Keyed<IHandler>(HandlerType.One);
builder.RegisterType<Handler2>().Keyed<IHandler>(HandlerType.Two);
builder.RegisterType<Handler3>().Keyed<IHandler>(HandlerType.Three);
var enabledHandlers = HandlerType.One | HandlerType.Three;
builder.RegisterType<Processor>().AsSelf()
.WithParameter(ResolvedParameter.ForKeyed<IEnumerable<IHandler>>(enabledHandlers));
答案 0 :(得分:1)
如果您可以在容器设置阶段提供适当的过滤器(就像在示例代码中那样),您可以将Processor
类型注册更改为以下内容:
builder.RegisterType<Processor>().AsSelf()
.WithParameter((p, c) => p.Name == "handlers",
(p, c) => new[]
{
c.ResolveKeyed<IHandler>(HandlerType.One),
c.ResolveKeyed<IHandler>(HandlerType.Three)
});
您需要使用的值可以从配置文件中随处获取。
答案 1 :(得分:0)
由于注册的处理程序基于配置开关,这意味着所选的处理程序不会在运行时更改。这与基于某些运行时条件选择处理程序非常不同。因此,我提出类似的建议:
var handlerIds = ConfigurationManager.AppSettings["Handlers"].Split(',');
if (handlerIds.Contains("1")) builder.RegisterType<Handler1>().As<IHandler>();
if (handlerIds.Contains("2")) builder.RegisterType<Handler2>().As<IHandler>();
if (handlerIds.Contains("3")) builder.RegisterType<Handler3>().As<IHandler>();
if (handlerIds.Contains("4")) builder.RegisterType<Handler4>().As<IHandler>();
// etc
builder.RegisterType<Processor>().AsSelf();