C# 温莎城堡注册意外行为

C# 温莎城堡注册意外行为,c#,castle-windsor,C#,Castle Windsor,我注意到一种奇怪的行为: public class Bar : IBar { ...something here } public class Foo : IBar { ...something here } container.Register(Component.For().ImplementedBy()); var test1=container.Resolve()//返回条 container.Register(Component.For().ImplementedBy()); va

我注意到一种奇怪的行为:

public class Bar : IBar
{
...something here
}

public class Foo : IBar
{
...something here
}
container.Register(Component.For().ImplementedBy());
var test1=container.Resolve()//返回条
container.Register(Component.For().ImplementedBy());
var test2=container.Resolve()//返回Foo
为什么test2是Foo?我没有将Foo注册为IBar,我已经明确地将其注册为Foo的实现。我认为只有Bar应该被解决,因为它是IBar的唯一实现。
这个项目不是我的。其他开发人员可能会进行一些奇怪的设置。

非常简短的回答是,如果单独执行,上面显示的代码将按照您的预期工作,返回
Bar
而不是
Foo
。如果返回的是
Foo
,则存在使用同一容器进行的其他组件注册

在这个场景中,单元测试是一种简单的方法,可以查看某个东西是否按照我们认为应该隔离的方式运行

此测试通过:

[TestMethod]
public void registration_returns_expected_type()
{
    var container = new WindsorContainer();
    container.Register(Component.For<IBar>().ImplementedBy<Bar>());
    var test1 = container.Resolve<IBar>(); //returns Bar
    container.Register(Component.For<Foo>().ImplementedBy<Foo>());
    var test2 = container.Resolve<IBar>();
    Assert.IsInstanceOfType(test2, typeof(Bar));
}
…然后,
IBar
被解析为
Foo

也可能发生的情况是,项目中有多个安装程序(实现
IWindsorInstaller
)来保持注册的小型化和可管理性,但它们包含冲突的注册。他们会被这样处决:

container.Install(FromAssembly.This());
…或使用从其他程序集中执行安装程序的命令

在这种情况下,启动时“获胜”的注册可能是不确定的。我一直被别人为同一个组件添加了不同的注册的情况所困扰,我的代码仍然运行良好,但在另一个环境中,另一个组件被选中

在大多数实际情况下,当我们设计接口时,我们知道它是用于运行时的单个实现还是多个实现。如果它是一个简单的应用程序,我们认为这不是一个问题,那么这可能不是一个问题

如果我们预先计划了多个实现——也许我们打算这样做——那么我们可以用命名的依赖项预先处理这个问题

container.Register(Component.For<IBar>().ImplementedBy<Bar>().IsDefault());
我不希望为了防止可能永远不会发生的冲突而不得不这样做

这就留下了几个选项,所有这些选项都有缺陷:

  • 意识到潜在的问题并注意它。我不喜欢将“小心”作为解决任何问题的方法,但在受到影响后,我发现这已经足够了
  • 运行集成测试,使用所有运行时组件配置容器,然后检查容器是否存在默认或非默认的重复注册。即使知道重复注册的可能性,我也从未觉得有必要这样做
  • 希望如果一个接口是如此通用,以致于它在应用程序范围内的组件中使用,那么您可以避免多个实现,或者在这种情况下,了解它的使用方式会导致明确的注册。在其他情况下,只需在需要的地方定义单独的接口
你是对的,这毫无意义。你能单独复制它吗?显然还有其他事情在发生。现在这是一个全面的答案好吧,你是对的——上面的例子不应该孤立地工作。但在我的情况下,它不知怎么起作用了。这不是另一个注册的问题-当我删除Foo实现的Foo时,坏事情得到了修复。如果这是另一个注册的问题,删除这一行不会改变任何事情。我搜索了另一个解决规则,但什么也没找到。虽然删除ti解决了问题,但我想知道将来如何修复它。
container.Install(FromAssembly.This());
container.Register(Component.For<IBar>().ImplementedBy<Bar>().IsDefault());
public class MyInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<NeedsBar>().DependsOn(Dependency.OnComponent<IBar, Foo>()));
    }
}