LightCore ServiceLocator在同一合同上进行多次注册

时间:2012-03-26 11:13:30

标签: c#-4.0 inversion-of-control design-patterns ioc-container service-locator

我们尝试将LightCore集成为Metadata- / ORM-Framework中的默认服务定位器。因此,我们喜欢框架内的一些默认注册,即Framework-User(= Application Developer)可以通过他自己的实现以某种方式“否决”(如果他喜欢这样做)。如何使用LightCore IoC容器或其他IoC容器来完成这项工作?

我们尝试了什么:

var builder = new ContainerBuilder();
builder.Register<Foo>().ControlledBy<SingletonLifecycle>();
builder.Register<Foo, Foo2>().ControlledBy<SingletonLifecycle>();

var container = builder.Build();

var foo = container.Resolve<Foo>();

我们注册了两个类作为Foo的合同。使用上面的代码,我们总是得到第一个(Foo的实例)返回。所以没有在这里推翻。顺便说一句:我们想得到一个Foo2的实例。

我们将其从使用具体类更改为使用接口:

var builder = new ContainerBuilder();
builder.Register<IFoo, Foo>().ControlledBy<SingletonLifecycle>();
builder.Register<IFoo, Foo2>().ControlledBy<SingletonLifecycle>();

var container = builder.Build();

var foo = container.Resolve<IFoo>();

有了这个,我们在Resolve&lt;&gt;()中得到一个解决异常,告诉我找不到注册。如果我们删除第二个“Register()”语句,它将以我们获取Foo实例的方式工作。

我们不确定是否错过了一些一般概念。这与其他IoC的工作原理相同吗?否决/覆盖注册的推荐方法是什么?

关于这个主题的任何帮助都会很棒 - 不仅仅适用于LightCore。

更新 我使用SimpleInjector IoC容器为上述场景设置了一些测试。使用此容器,需要在构造函数中指定AllowOverridingRegistration = true,它将按预期工作。所以看起来LightCore只是不能正确支持这个用例,但其他人也这样做。

更新 我们得到了LightCore创建者的快速回复,称LigtCore根本不支持覆盖注册。所以似乎没有办法解决这些场景注册覆盖LightCore所以我们从LightCore切换到SimpleInjector。

以下SimpleInjector配置符合我们当前的四个要求:

  // Register concrete class for FooFoo
  container.RegisterSingle<FooFoo>();

  // Register concrete classes for Foo - Final registration should return FooFoo, not Foo
  container.RegisterSingle<Foo>();
  container.RegisterSingle<Foo, FooFoo>();

  // Register interfaces for IFoo - Final registration should return FooFoo, not Foo
  container.RegisterSingle<IFoo, Foo>();
  container.RegisterSingle<IFoo, FooFoo>();

  // Register list of Plugs
  container.RegisterAll(new IPlug[] { new PlugA(), new PlugB() });

干杯,马克

1 个答案:

答案 0 :(得分:1)

AFAIK所有大型DI框架(Autofac,Unity,Castle Windsor,StructureMap,Ninject)都具有覆盖注册的功能。他们中的大多数通过对同一服务类型进行多次注册来允许这种情况,并且他们选择其中一个注册作为默认注册。然而,他们选择哪个实例,每个框架都不同。虽然有些框架选择了多个注册中的第一个,但其他框架选择了最后一个注册。知道选择框架如何做到这一点很重要,因为这决定了你是应该在所有其他人之前或之后注册“覆盖”实例。

因为所有这些框架都有不同的重载分辨率,所以我决定让Simple Injector默认没有任何覆盖行为(虽然它是可配置的,正如你已经注意到的)。这使得迁移到另一个框架变得更加容易,这是Simple Injector的设计目标之一。但是,默认情况下允许注册被覆盖,也可能是配置错误的来源,这可能是耗时的追踪。由于Simple Injector应该很容易入手,因此禁止覆盖是有意义的(默认情况下)。

使用Simple Injector,当启用AllowOverridingRegistration时,新注册确实替换了同一类型的早期注册。这与其他容器不同,后者通常保留其他注册,并允许您将所有这些注册解析为单个集合。使用Simple Injector,必须单独注册一组内容,并且可以单独覆盖。

除了简单注射器之外的所有其他容器以及我不能说的大容器。但是,我认为压倒一切对他们中的大多数都很难。