这是我的方案的简化。
我有一些接口IFoo
,IBar
和IBaz
及其实施Foo
,Bar
和Baz
。
Foo
取决于IBar
,Bar
取决于IBaz
,因此依赖关系图如下所示:
Foo
|
Bar
|
Baz
My Windsor配置看起来像这样,一切都按预期工作:
container.Register(Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IBar>().ImplementedBy<Bar>());
container.Register(Component.For<IBaz>().ImplementedBy<Baz>());
现在我需要引入一个新的SpecialBaz
,当我的依赖图以Baz
开头时,我希望使用它而不是旧的Foo
。该应用的其余部分将继续使用旧的Baz
:
Foo SomethingElse
| |
Bar Bar
| |
SpecialBaz Baz
我尝试使用SpecialBaz
api:
ServiceOverride
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>()));
但两种方法都不奏效。
Castle Windsor有可能这样做,我该如何连线?
答案 0 :(得分:2)
短答案是是 - Castle Windsor可以。每个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;
}
}
}}