autofac中的条件组件注册

是否可以有条件地在其他组件的状态上注册组件? 就像是:

ContainerBuilder.RegisterConditionally( Func, Func); 

我发现在autofac的V2之前,可以使用“ Register().OnlyIf() ”构造,它看起来像我正在寻找的那个。 我希望此function有条件地覆盖默认注册。

 class CommonRegistrations { public virtual void Register(ContainderBuilder builder) { builder.Register(ctx => LoadSettings()).As().SingleInstance(); builder.RegisterType().As(); } } class SpecificRegistrations : CommonRegistrations { public virtual void Register(ContainerBuilder builder) { base.Register(builder); builder.ConditionalyRegister( ctx => ctx.Resolve().ReallyUseSpecificFoo, ctx => new SpecificFoo()).As(); } } ... var builder = new ContainerBuilder(); var registrations = new SpecificRegistrations(); registrations.Register(builder); var container = builder.Build(); IFoo foo = container.Resolve(); 

根据ISettings.ReallyUseSpecificFoo ,foo将是DefaultFoo实例或SpecificFoo实例。

谢谢。

无法根据容器内容在容器级别执行条件注册。 麻烦的是你需要在容器中解决一些问题,以便确定在容器中注册的内容,这在技术上可能会影响你是否想要首先注册该东西。 鸡/蛋循环依赖问题。

但是,您可以有条件地将事物注册到嵌套的生命周期范围中。 大多数集成点(如ASP.NET)都会解析嵌套生命周期范围(如HTTP请求长度生命周期范围)。 您可以动态地将事物注册到嵌套的生命周期范围中,这可能会解决您的问题。

 var builder = new ContainerBuilder(); builder.Register(ctx => LoadSettings()).As().SingleInstance(); builder.RegisterType().As(); var container = builder.Build(); var settings = container.Resolve(); using(var scope = container.BeginLifetimeScope(b => { if(settings.ReallyUseSpecificFoo) { b.RegisterType().As(); } }) { // Resolve things from the nested lifetime scope - it will // use the overrides. This will get the SpecificFoo if the // configuration setting is true. var foo = scope.Resolve(); } 

另一个选择是使注册成为lambda。 它可能会使注册本身更复杂,但它是您可以考虑的选项。

 var builder = new ContainerBuilder(); builder.Register(ctx => { var settings = ctx.Resolve(); if(settings.ReallyUseSpecificFoo) { return new SpecificFoo(); } return new DefaultFoo(); }).As(); 

如果手动构造没有吸引力,您也可以通过Autofac传递它。

 var builder = new ContainerBuilder(); // Register the IFoo types - but NOT "As" builder.RegisterType(); builder.RegisterType(); // In the lambda use Resolve to get the instances. builder.Register(ctx => { var settings = ctx.Resolve(); if(settings.ReallyUseSpecificFoo) { return ctx.Resolve(); } return ctx.Resolve(); }).As(); 

另一种选择是在构建之后更新现有容器。 在这种情况下,您可以通过实际构建容器,使用它以及在事后更改注册来避免鸡/蛋场景。

 var builder = new ContainerBuilder(); builder.Register(ctx => LoadSettings()).As().SingleInstance(); builder.RegisterType().As(); var container = builder.Build(); var settings = container.Resolve(); if(settings.ReallyUseSpecificFoo) { var updater = new ContainerBuilder(); updater.RegisterType().As(); updater.Update(container); } 

最后,您可以考虑XML配置。 鉴于注册依赖于某种配置设置,您可以考虑使用Autofac的XML配置支持 。 这样,您可以指定使用XML配置进行注册并在第一次注册正确的内容时,而不是尝试从未构建的容器中解析某些内容以有条件地注册其他内容。