【问题标题】:How to specify a service override further down the dependency graph in Castle Windsor?如何在 Castle Windsor 的依赖图中进一步指定服务覆盖?
【发布时间】:2017-10-11 09:16:03
【问题描述】:

这是我的场景的简化。

我有一些接口IFooIBarIBaz 以及它们的实现FooBarBaz

Foo 依赖于IBarBar 依赖于IBaz,所以依赖图如下所示:

   Foo 
    |
   Bar
    |
   Baz

我的 Windsor 配置如下所示,一切正常:

container.Register(Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IBar>().ImplementedBy<Bar>());
container.Register(Component.For<IBaz>().ImplementedBy<Baz>());

现在我需要引入一个新的SpecialBaz,当我的依赖关系图以Foo 开头时,我想使用它而不是旧的Baz。该应用的其余部分将继续使用旧的Baz

      Foo           SomethingElse
       |                  |
      Bar                Bar
       |                  |
   SpecialBaz            Baz

我尝试用ServiceOverride api 命名SpecialBaz

container.Register(Component.For<IBaz>().ImplementedBy<Baz>().IsDefault());
container.Register(Component.For<IBaz>().Named("special baz").ImplementedBy<SpecialBaz>());

container.Register(Component.For<IFoo>()
                            .ImplementedBy<Foo>()
                            .DependsOn(ServiceOverride.ForKey<IBaz>().Eq("special baz")));

并指定依赖:

container.Register(Component.For<IBaz>().ImplementedBy<Baz>().IsDefault());
container.Register(Component.For<IBaz>().ImplementedBy<SpecialBaz>());

container.Register(Component.For<IFoo>()
                            .ImplementedBy<Foo>()
                            .DependsOn(Component.For<IBaz>().ImplementedBy<SpecialBaz>()));

但是这两种方法都不起作用。

这在温莎城堡是否可行,我该如何接线?

【问题讨论】:

  • 请在首次注册IBaz时尝试删除IsDefault()
  • 是 IFoo 的 Foo 和 SomethingElse 实现吗?
  • @PhilDegenhardt 恐怕没有用。也不要忘记Baz 在这种情况下是IBaz 的默认实现,其他人都应该是它的一个实例。当依赖关系图以Foo 开头时,应该使用SpecialBaz
  • @OgnyanDimitrov 不,SomethingElse 是一个不同的类,它也依赖于 IBar -&gt; IBaz 依赖图。

标签: c# dependency-injection inversion-of-control castle-windsor


【解决方案1】:

简短的答案是是的 - 温莎城堡可以。每个 DI 容器都可以。我将为您提供一条规则,以帮助您解决大部分依赖问题。

答案。

规则:每个间接点都需要一个抽象层。当您尝试在应用程序中构建依赖关系解析时,请记住此规则。据我所知,有两种间接方式 - 静态和动态。

您需要在一点仅更改一次间接)更改图表,但不知何故您需要在运行时遍历依赖关系图表看看你的 Baz 是否被请求 Foo。所以你需要某种类型的工厂(抽象事物)。

根据一个问题的答案,您有两种选择

我的更改取决于静态还是动态条件?

例如 - 如果您依赖传入的用户数据或环境数据 - 您处于动态情况下,您需要使用 Dynamic Parameters 或其他功能。

在你的情况下,你的依赖是静态的。

当我的依赖关系图以 Foo 开头时,我想使用它而不是旧的 Baz。

一旦图表的开头是 Foo,特殊 Baz 的条件就永远不会改变。

您可以使用 Factory 方法或 Typed Factory Componend Selector 来实现此目的。我为你提供了一个工厂方法的例子:

using System;
using Castle.MicroKernel.Registration;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var container = new Castle.Windsor.WindsorContainer();
            container.Register(Component.For<IFoo>().ImplementedBy<Foo>());
            container.Register(Component.For<ISomethingElse>().ImplementedBy<SomethingElse>());

            container.Register(Component.For<IBar>().ImplementedBy<Bar>().LifeStyle.Transient);

            container.Register
            (
                Component
                .For<IBaz>()
                .UsingFactoryMethod
                (
                    (k, c) =>
                    {
                        IBaz resolved = null;
                        var requestingType = c.Handler.ComponentModel.Implementation;
                        if (requestingType == typeof(Foo))
                        {
                            resolved = new Baz();
                        }
                        else
                        {
                            resolved = new BazSpecial();
                        }

                        return resolved;
                    }
                ).LifeStyle.Transient
            );

            var f = container.Resolve<IFoo>();
            var se = container.Resolve<ISomethingElse>();

            Console.ReadLine();
        }
    }
    internal interface IBar
    {
    }

    internal interface IBaz
    {
    }

    internal interface IFoo
    {
    }

    interface ISomethingElse
    {

    }


    internal class Bar : IBar
    {
        private readonly IBaz baz;

        public Bar(IBaz baz)
        {
            this.baz = baz;
        }

    }

    internal class Baz : IBaz
    {
    }

    internal class BazSpecial : IBaz
    {
    }

    internal class Foo : IFoo
    {
        private readonly IBar bar;

        public Foo(IBar bar)
        {
            this.bar = bar;
        }
    }

    internal class SomethingElse : ISomethingElse
    {
        private readonly IBar bar;

        public SomethingElse(IBar bar)
        {


         this.bar = bar;
        }
    }
}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多