我正在为自己编写一个小实用程序,因此当我当前使用 Unity 时,如果可以解决此问题,我可以更改为不同的 IoC 容器。
我想创建一个类,该类在创建时会给出一些数据,但之后是不可变的,通常我会这样做:
class SomeItem
{
public SomeItem(string name)
{
Name = name;
Hash = new SomeHashingClass().GenerateHash(name);
}
public string Name { get; private set; }
public string Hash { get; private set; }
}
问题是构造函数中对 SomeHashingClass 的依赖,如何在保持对象不可变的同时注入(inject)它?
一种方法是让构造函数只接受依赖项,然后使用与当前构造函数相同的方法来完成实际工作。然而我讨厌这个想法,因为它可能会使对象处于存在但完全无效的状态。并且需要编写代码以确保该方法只能被调用一次。
我看到的另一种方法是创建一个统一解析的“SomeItemFactory”类,然后手动为 SomeItem 进行依赖注入(inject),但这会使代码量增加一倍:
class SomeItemFactory
{
IHashingClass _hashingClass;
public SomeItemFactory(IHashingClass hashingClass)
{
_hashingClass = hashingClass;
}
public SomeItem Create(string name)
{
return new SomeItem(_hashingClass, name);
}
}
class SomeItem
{
public SomeItem(IHashingClass hashingClass, string name)
{
Name = name;
Hash = hashingClass.GenerateHash(name);
}
public string Name { get; private set; }
public string Hash { get; private set; }
}
请告诉我有一种干净的方法可以做到这一点。为什么没有这样的方法:
unityContainer.Resolve<SomeItem>("the items name");
最佳答案
虽然您确实可以将参数传递给 Resolve 方法,但请仔细考虑这是否确实是正确的设计。
你为什么要这样做?是因为您想使用 Unity 作为服务定位器吗?这确实是我能想到的唯一原因,但是I consider this an anti-pattern .
DI容器的使用应遵循好莱坞原则:告诉它resolve the entire application graph at the Composition Root然后忘记这一切。
在您的特定情况下,您可以保持 SomeItem 不变,但如果您希望能够将 HashingClass 作为依赖项进行更改,则需要将其注入(inject)到 SomeItem 中,并且构造函数注入(inject)是最好的选择。
如果您的应用程序中只需要一个 SomeItem 实例,您可以像在 Unity 中那样将其连接起来,但如果您需要创建多个实例,则 Abstract Factory is the correct approach .
您的示例已经差不多了:您只需从 SomeItemFactory 中提取一个接口(interface),并在任何需要创建 SomeItem 实例的使用者中依赖此 ISomeItemFactory。
它可能看起来像是更多的代码,但在任何情况下(无论哪种方式),代码行都不是一个特别好的代码质量度量标准。但是,这种方法允许您遵循 Single Responsibility Principle并相互独立地改变 SomeItem 的创建和散列。
请注意,these principles 都没有专门针对 Unity,但广泛适用于一般 DI。
关于c# - 不可变类和统一应用程序 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2258629/