控制反转和内部 类

Inversion of control and internal classes

我有三个关于控制反转的问题。

我正在使用 C# 构建一个国际象棋程序,我已将代码分解为多个 class 库。这个想法是将所有关于棋盘位置和棋子移动的逻辑封装在一个地方,所有关于检索和写入游戏数据的逻辑都封装在另一个地方,所有关于显示棋盘及其棋子的数据在第三个地方(UI).

我有一个库,它是应用程序的 "business layer",包含代表游戏、玩家、棋盘、棋盘上的方块和棋子的界面和 classes。每个对象都有一个 public 接口。然而,实现这些接口的 classes 是内部的。在我看来,这种方法将阻止库外部的代码实例化甚至了解任何内部结构,并且是正确的方法。客户应该只使用接口的方法和属性。

第一个问题:这种方法是否可行,或者它是否以某种方式违反了 DI 原则?

我一直在纠结是否应该向 IoC 注册 IPiece 接口,甚至 IGame 以外的任何接口。这是因为我希望客户端只能创建实现 IGame 的对象,并且实现其他接口的所有对象都随之而来。 (我的意思是,你创建一个新游戏,你得到一个包含所有 64 个方块和 32 个现成棋子的棋盘。或者你检索一个保存的游戏,棋盘和方块被创建,棋子放在他们的以前的位置。客户无需执行任何操作)。

第二个问题:这样可以吗还是违反了依赖注入原则?

IPiece 界面定义了一件作品所需的所有功能,而不管它是哪种作品。甚至还有一个 属性 可以被 UI 用来为图像构建资源 ID 来显示作品,所以客户端不需要知道 class的一块是。

问题是有一个抽象基础 class 实现了名为 PieceIPiece 接口和从它继承的 6 个子 classes(BishopKnightKingQueenRookPawn)。我不知道如何针对 IPiece 界面注册所有这些 classes,或者即使我应该。

我不希望客户不得不担心他们正在使用哪种类型的作品,或者如何创建它们。当开始新游戏时,通过 IGame 界面上的方法自动创建棋子并放置在棋盘上。加载已保存的游戏后,将通过同一界面中的另一种方法创建棋子并将其移动到棋盘上的已保存位置,客户端无需执行任何操作,只需检索数据并将其传递给该方法即可。这意味着在国际象棋引擎库中,内部 classes 是在不使用 IoC 的情况下实例化的。

这个想法是客户端只是迭代所有的部分并将它们绘制在屏幕上正确的位置,而不需要知道对象的 class。客户端需要的所有信息都在 IPiece 接口定义的属性中提供。

第三个问题:这样可以吗,还是我应该定义 IBishop 等并将 classes 注册到接口 IoC,即使 IoC 映射永远不会在 class图书馆?

  1. 理论上你应该没问题。但是,考虑到 IoC/DI 的最大好处是它可以使测试变得容易得多,您可能需要在测试时参考实现。话虽这么说,您可以求助于 InternalsVisibleToAttribute,或者如果您不打算进行单元测试则可能不需要这样做(尽管我强烈建议这样做);
  2. 你的推理在这里也听起来不错。您可以以极简主义的方式做到这一点:首先不注册任何东西,运行 代码和注册类型,而不是更早;
  3. 和以前一样,在需要知道的基础上继续;或者如果它适合您的情况,请采纳@Tone 的建议 - 拥有一个带有实现的 IPieceFactory 以保持所有创建逻辑。