1

我想针对其相应的接口注册一个单例类。我发现了两种不同的方法来实现这一点:

选项1:

this.For<ISomeClass>()
    .Use<SomeClass>()
    .Singleton();

选项 2:

this.For<ISomeClass>()
    .Use(c=>c.GetInstance<SomeClass>())
    .Singleton();
this.ForConcreteType<SomeClass>()
    .Configure
    .Singleton();

那么这两个调用是相同的还是两者之间有区别?显然,选项 1 由于其简洁性而更可取。

4

1 回答 1

2

结果将是相同的,但第二个示例执行了一个额外的步骤。它真的很小。但更简单的语法更好。

第一个例子说,当需要 时ISomeClass,用 来满足它SomeClass。如果已创建实例,请使用它。如果没有,请创建一个实例。

第二个例子说当需要时ISomeClass,通过调用一个匿名函数来实现它,该函数将返回一个实现ISomeClass。该函数解析并返回SomeClass.

考虑到幕后正在进行的大量工作,再调用一个匿名函数并不会产生太大的影响。

更大的担忧是更复杂的方法如何混淆其他开发人员并产生问题。这不是假设。我已经看到了,结果不是很好。

后面的开发人员可能不了解 IoC 容器应该如何工作,他们所能做的就是按照您的示例进行操作,直到他们理解为止。因此,树立正确的榜样很重要,否则他们可能会完全错过重点。我见过这样的工厂方法:

this.For<ISomeClass>()
    .Use(c=> new SomeClass(
        c.GetInstance<ISomethingElse>(), 
        c.GetInstance<ISomeOtherThing>(),
        c.GetInstance<ITenMoreOfThese>()
));

然后他们开始像这样创建对象,解析实例,并使用 DI 注册将实例注入对象。当然,偶尔会有这样做的正当理由。但是它会污染你的 IoC 代码,直到改变一个类的依赖关系变得很痛苦,这是容器应该解决的问题之一。

这实际上滚雪球更多。现在开发人员不想接触越来越脆弱和令人困惑的 IoC 代码,因此他们停止创建新类,开始将新功能塞进现有方法中,并且从不重构任何东西。IoC 应该使重构和更小的类和接口变得更容易,但最终却让这一切变得更加困难。这会导致各种新的代码异味和腐烂。

所以我推荐“无破窗”方法——使用遵循 IoC 原始意图的最简单语法——尽可能为接口指定实现类型,而不是解析并返回实现的函数。

于 2018-02-20T14:00:07.307 回答