c# - 在构造对象实例时,分离 DI 和数据参数的有效方法是什么?
问题描述
我正在尝试为需要将 DI(服务)和其他参数(数据模型)传递给类进行初始化的场景找到一个优雅的解决方案。
对于数据模型(简单的类和结构),我们可以这样做:
class Board
{
public Dimension Dimension { get; }
public Tile[] Tiles { get; }
public Piece[] Pieces { get; }
public Board(Dimension dimension)
{
Dimension = dimension;
// Initialize Tiles here
// Initialize Pieces here (not all tiles will have a piece)
}
public bool TryGetPiece(Tile tile, out Piece piece)
{
// Search for the piece...
return true;
}
public bool TryMovePiece(Tile tileFrom, Tile tileTo)
{
// Try moving new piece...
return true;
}
}
在这里,我们不需要任何 DI。我们只是通过构造函数传递 Dimension 参数。
对于服务(纯粹的(如果这是正确的术语)),我们会这样做:
class PieceMovingService
{
public PieceMovingService(AllKindsOfDiItems)
{
// DI items initialised here...
}
public void PerformBestMove(Board board)
{
// All kinds of thinking....
// Still thinking...
// Finally found where to move the piece to
// Move the piece
board.TryMovePiece(A, B);
}
public void SomeOtherRelatedStuff(Board board)
{
// Blah blah lah
}
}
但有时我真的想将 Board 实例作为构造函数参数传递给 PieceMovingService 类(我也阅读并消化了这个构造函数参数与方法参数?):
class PieceMovingService
{
public Board Board { get; }
public PieceMovingService(AllKindsOfDiItems, Board board)
{
// DI items initialized here...
Board = board;
}
但是,我不喜欢将 DI 与此数据模型混合使用。我开始谷歌,发现这篇文章Combining DI with constructor parameters? 但公认的答案表明应该避免这种结构。不幸的是,这个答案对我来说似乎不完整。它只是不点击。
我也对通过构造函数传递 DI 的方法不满意。DI 论点对我来说有点“如何”的味道。这些是实现细节的一部分,如果我决定更改方法并且如果 DI 列表发生更改,则需要重构整个构造函数,并且项目中此类的所有实例都需要相应地重构。另一方面,Board 参数的传递考虑到它是要操作的主要对象,因此具有“什么”的味道;不管方法是如何实现的,这个对象仍然是必需的;没有它 PieceMovingService 没有任何意义。
我深思熟虑后决定将我的 DI 实例化为具有默认值的私有属性,这样我就不必在构造函数中传递它们。但在这种情况下,没有发生 IoC,我无法从外部传递任何其他东西。如果我将这些属性公开,我会解决这个问题,但我会引入副作用,因为我可以在同一个实例上一遍又一遍地更改这些 DI 项目并为方法获得不同的结果(出于某种原因,当 Board 依赖时我可以造成副作用,但当 DI 服务这样做时就不行了)。
此外,还有一个问题是某些 DI 需要自己的 DI,因此会导致丑陋的链接。
所以我一直在想......然后我想出了这个模式:
class A
{
private Dependency1 dependency1;
private Dependency2 dependency2;
private A(int number)
{
}
public class AFactory
{
private readonly Dependency1 dependency1;
private readonly Dependency2 dependency2;
public AFactory(Dependency1 dependency1, Dependency2 dependency2)
{
this.dependency1 = dependency1;
this.dependency2 = dependency2;
}
public A Create(int number)
{
return new A(number)
{
dependency1 = dependency1,
dependency2 = dependency2
};
}
}
}
它解决了我之前解决的问题,但引入了另一个问题,现在我根本无法在没有工厂的情况下实例化 A 类。因此,我必须执行以下操作:
var aFactory = new AFactory(new Dependency1(), new Dependency2());
var a = aFactory.Create(5);
感觉它没有任何优势或任何东西,只是让它变得更麻烦。在这一点上,感觉就像在构造函数中混合 DI 和数据模型毕竟不是那么糟糕,这让我回到了方 1。
所以我的问题是:在构造对象实例时,分离 DI 和数据参数的有效方法是什么,这样类的用户就不必一直处理传递 DI 并且能够只关注“什么”,而不是“如何”?
解决方案
推荐阅读
- angular - Angular 7 和 IE
- javascript - 使用javascript在html中按类用空字符串替换文本
- javascript - 获取有关事件更改 vue 和 laravel 的数据的问题
- python - 从 DataFrame 列中提取特定字符/文本
- node.js - 控制器和中间件有什么区别
- prometheus - 如何比较指标名称中具有相同数字的一系列指标
- git - git checkout -p 指定编码
- flutter - 如何在 iOS 上修复“找不到应用程序”(AppAvailability)
- r - 将绘图保存为 pdf 文件的更快方法(而不是 orca)
- excel - 如何在word中使用“选择”在excel中使用VBA代码移动光标?