2

在依赖注入中,假设我在 AssemblyA 中有一个Consumer AssemblyB 中一个依赖实现。我正在使用构造函数注入,以便将依赖项的抽象作为构造函数参数传递给消费者。抽象驻留在哪个程序集中?AssemblyA 或 AssemblyB 或其他一些程序集(AssemblyC)以便 AssemblyA 和 AssemblyB 可以引用来自 AssemblyC 的抽象?

4

3 回答 3

2

据我了解,你有;

class AssemblyA.ClassA
{
    public ClassA(ClassB arg) { ... }
}

abstract class AssemblyB.ClassB
{ }

class AssemblyC.ClassC : AssemblyB.ClassB // some concrete implementation of ClassB
{  }

然后;

  • ClassB 可以属于 AssemblyA 或 AssemblyB - 在这种情况下,AssemblyA 引用 AssemblyB
  • ClassC 可以属于 AssemblyA、AssemblyB 或 AssemblyC - 在这种情况下,AssemblyA 引用AssemblyBAssemblyC,而 AssemblyC 引用 AssemblyB

这是您的问题的琐碎化。

于 2012-06-04T10:39:29.623 回答
1

您要问的是所谓的依赖倒置,是 SOLID 原则之一。依赖倒置说你应该依赖抽象而不是实现。它还指出,较低层不应该知道较高层。

考虑到这一点,一切都很清楚=)

IUserService // abstraction, where should this be placed?
DbUserService //implementation, placed in YourApp.Core
UserController(IUserService) // usage, placed in YourApp.UI

好。由于较低层(核心)不应该知道较高层(UI),我们不能将界面放置在 UI 项目中。

所以我们有两个选择:第三个程序集或核心程序集。

还有另一个称为“分离接口”的原则,它指出接口应该放在另一个包/程序集中。

我通常将接口与实现放在同一个包中以保持简单。

于 2012-06-04T13:53:55.523 回答
0

简答

抽象(包括接口)属于调用者

更长的答案

查看 DI 维基百科文章的实现部分

这显示了两种实现:

  • 抽象属于更高级别的组件
  • 抽象在它们自己的包中

要理解这一点,重要的是要理解抽象在依赖倒置中试图做什么。目标是让更高级别的流程根据自己的术语定义依赖关系,但让其他人稍后提供实现。这允许高层流程在低层实现发生变化时避免变化,并灵活​​地交换不同的实现。

如果接口与实现耦合,那么我们就达不到这个目标,因为接口不是抽象的。接口会随着实现而改变,并且更高级别的流程不会与变化隔离。

还要考虑包依赖结构。如果接口属于实现,则高级流程必须引用任何用例的低级包。但是,如果抽象属于高层流,那么我们可以根据不同的用例引用不同的实现。这是基础架构,如Ports and AdaptersClean Architecture。我认为马克西曼描述得很好

于 2021-10-03T16:37:43.160 回答