Castle Windsor中多个不同的对象图实例

时间:2014-05-16 14:07:52

标签: c# castle-windsor

这是我的设置的简化版本。我有一个使用库的应用程序,该库提供了一个访问某些Web服务的客户端。我的应用程序将它包装在一个提供更高级别操作的XyzService中。

该库提供了一个参数化的Windsor安装程序,它可以注册WebApiClient及其依赖项。安装程序获取一个配置对象(除其他外)指定Web服务的URI。

只要我只想与Web服务的单个实例交谈,这就没问题了。但在这种情况下,实际上有两个不同的Web服务实例,它们不可互换。在启动时,我想要构建应用程序,引用两个不同的XyzService实例,第一个配置为访问(例如)http://server.green/的对象图,第二个配置为访问的对象图(例如) http://server.red/

这是一个图表:

Example object

如果我只有两个类型为IXyzService的构造函数参数,那么左边是我得到的。我得到两个WebApiClient实例(因为它有瞬态生命周期),但它们都共享相同的配置(因为安装程序创建了一个实例并注册了它)。

右边是我想要的。但我不确定如何提供两个IWebApiClientConfigurations并告诉Castle Windsor,当它解析IXyzServices for App时,它应该创建两个单独的对象图,第一个有一个配置,第二个有另一个。

我尝试了什么

我起初认为typed factory可能是我想要的。我创建了一个这样的界面:

public interface IXyzServiceFactory
{
    IXyzService GetXyzService(IWebApiClientConfiguration webApiClientConfiguration);
    void Release(IXyzService xyzService);
}

并将其注册为:

container.Register(
    Component.For<IXyzServiceFactory>()
             .AsFactory());

我更改了我的应用程序以获取此工厂并使用它来请求两个IXyzService实例,每次都传递不同的配置。我认为在尝试构建WebApiService时可能会使用该配置。但是:

  • 它不起作用 - 我传入的配置对象被忽略了,我仍然得到了库安装程序提供的配置实例。
  • 即使它有效,但它本身也很讨厌,因为它知道配置对象和XyzService的生命周期,使我的应用程序混乱。

我想要什么

理想情况下,我想知道如何告诉Windsor当它调用App的构造函数时:

public App(IXyzService xyzService1, IXyzService xyzService2)

...它应该为每个正常构建一个对象图,除了解决IWebApiClientConfiguration时,第一个图应该得到一个实例而第二个图应该得到另一个。我想在App的Windsor安装程序中实例化并注册IWebApiClientConfiguration的实例。

我不想在我的应用程序中复制库的Windsor安装程序,我希望它注册的所有内容除了 WebApiClientConfiguration。但如果没有办法绕过它,我会忍受这样做。

虽然我对使用库可以做些什么感到有限,但我仍然会对那些建议如何在没有这些限制的情况下处理这种情况的答案感兴趣。

备注

我目前正在使用Castle Windsor 2.5.3。我知道这很老了。如果解决方案需要它,我会愿意尝试升级,假设没有任何突破性的更改会阻止我使用库及其现有的安装程序。如果有升级则很难。

我试图删除无关的细节,而不会让事情变得如此抽象,以至于动机不再明确。请告诉我是否有办法澄清问题而不会过长。

1 个答案:

答案 0 :(得分:1)

在Castle Windsor的3.x版本中,您可以将多个实现注册为命名,然后在其他注册中明确指定命名依赖项。它看起来像这样(当然这个注册缺少实现,生活方式......但这些并不重要):

container.Register(
    // Register a config containing http://server.green/, set its name,
    // and register a named IXyzService depending on the config.
    Component.For<IWebApiClientConfiguration>().Named("greenConfig"),
    Component.For<IXyzService>().Named("greenService")
        .DependsOn(typeof (IWebApiClientConfiguration), "greenConfig"),

    // Register another config of the same interface containing http://server.red/,
    // and a named IXyzService that uses it.
    Component.For<IWebApiClientConfiguration>().Named("redConfig"),
    Component.For<IXyzService>().Named("redService")
        .DependsOn(typeof (IWebApiClientConfiguration), "redConfig"));

然后,您可以使用其名称作为密钥来解析服务:

var greenService = container.Resolve<IXyzService>("greenService");
var redService = container.Resolve<IXyzService>("redService");

并且每个实例都将使用其指定的命名依赖项。

应该有一种(不同的)方式来指定Castle Windsor 2.5.3版本中的依赖关系,虽然我还没有使用它,所以我不知道如何实现这一点。