假设我有两个由 CaSTLe Windsor 实例化的类,每个类都依赖于同一个接口(interface):

  • FooRepoIApiClient
  • BarRepoIApiClient

  • 在这种情况下,IApiClient 由一个类 GenericApiClient 实现,该类知道如何与任何 API 通信。但是,我想创建传递不同配置值(通过 GenericApiClient 公开)的 IApiClientConfiguration 的不同实例,以便 FooRepo 与 Foo API 端点对话,而 BarRepo 与 Bar API 端点对话:
  • FooRepoIApiClient (GenericApiClient)IApiClientConfiguration (FooClientConfiguration)
  • BarRepoIApiClient (GenericApiClient)IApiClientConfiguration (BarClientConfiguration)

  • 这是我迄今为止尝试过的:
    container = new WindsorContainer();
    container.Register(
        Component.For<HomeController>().LifeStyle.Transient,
        Component.For<FooRepo>()
            .LifeStyle.Transient,
        Component.For<BarRepo>()
            //.DependsOn(Dependency.OnComponent<IApiClientConfiguration, BarClientConfiguration>()) // this does nothing cause the client config is not a direct dependency :(
            .LifeStyle.Transient,
        Component.For<IApiClient>()
            .ImplementedBy<GenericApiClient>()
            //.DependsOn(Dependency.OnComponent<IApiClientConfiguration, BarClientConfiguration>()) // this overrides for both FooRepo and BarRepo :(
            .LifeStyle.Transient,
        Component.For<IApiClientConfiguration>()
            .ImplementedBy<FooClientConfiguration>()
            .LifeStyle.Transient,
        Component.For<IApiClientConfiguration>()
            .ImplementedBy<BarClientConfiguration>()
            .LifeStyle.Transient);
    

    我无法弄清楚如何获取 FooRepo 以获取使用 GenericApiClient 配置的 FooClientConfiguration 实例,而 BarRepo 获取 BarClientConfiguration :
  • 默认情况下,他们都获得 FooClientConfiguration 因为这是首先注册的
  • 我可以使用 IApiClient 覆盖 DependsOn(...) 的配置,但这适用于 FooRepoBarRepo
  • 如果我在 DependsOn(...) 上使用 BarRepo ,它没有效果

  • (如果上述问题不清楚,我有一个最小的工作示例 here )

    有什么方法可以配置温莎城堡来做我想做的事吗?有什么方法可以更好地构建我的代码,这样我就不会遇到这个问题吗?

    最佳答案

    container.Register(
        Component.For<IApiClientConfiguration>()
            .ImplementedBy<FooClientConfiguration>()
            .Named("FooConfiguration")
            .LifestyleTransient(),
        Component.For<IApiClientConfiguration>()
            .ImplementedBy<BarClientConfiguration>()
            .Named("BarConfiguration")
            .LifestyleTransient(),
        Component.For<IApiClient, GenericApiClient>()
            .Named("FooClient")
            .DependsOn(Dependency.OnComponent(
                typeof(IApiClientConfiguration), "FooConfiguration")),
        Component.For<IApiClient, GenericApiClient>()
            .Named("BarClient")
            .DependsOn(Dependency.OnComponent(
                typeof(IApiClientConfiguration), "BarConfiguration")),
        Component.For<FooRepo>()
            .DependsOn(Dependency.OnComponent(typeof(IApiClient), "FooClient")),
        Component.For<BarRepo>()
            .DependsOn(Dependency.OnComponent(typeof(IApiClient), "BarClient"))
        );
    

    它不漂亮。并且可能有一种方法可以稍微简化语法。温莎通常提供几种不同的方式来做所有事情。

    您正在定义 GenericApiClient 的两个不同实现,并且为每个实现指定要使用的配置。然后,在注册 FooRepoBarRepo 时,您要为它们中的每一个指定要使用的 IApiClient 的命名实现。

    如果一个或另一个是默认值,那么您可以使用 IsDefault() 指示它并且只命名另一个。如果您为不同的实现组编写单独的安装程序,甚至只是同一安装程序中的方法,也可以更容易遵循,例如
    RegisterFooDependencies(IWindsorContainer container)
    {
        container.Register(
            Component.For<IApiClientConfiguration>()
                .ImplementedBy<FooClientConfiguration>()
                .Named("FooConfiguration")
                .LifestyleTransient(),
            Component.For<IApiClient, GenericApiClient>()
                .Named("FooClient")
                .DependsOn(Dependency.OnComponent(
                    typeof(IApiClientConfiguration), "FooConfiguration")),
            Component.For<FooRepo>()
                .DependsOn(Dependency.OnComponent(typeof(IApiClient), "FooClient"))
        );
    }
    

    关于c# - 覆盖为嵌套/传递依赖项注入(inject)的组件实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38213376/

    10-10 19:51