c# - 不可变类和统一应用程序 block

标签 c# .net dependency-injection ioc-container immutability

我正在为自己编写一个小实用程序,因此当我当前使用 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/

相关文章:

c# - 如何使用 C# 动态设置 html 链接 <a href>

c# - 默认情况下路由到 Index 之外的另一个操作

c# - 在控制台应用程序中实例化 WinForm

C# WPF 按钮 "Content"未显示

.net - .Net Core EF中如何组合多个条件表达式来过滤数据?

c# - 关于C#中数组浅拷贝的问题

c# - Parallel.Invoke 中的 DataBind() 由于堆栈为空而失败。错误

javascript - 如何从独立的纯 JavaScript 函数调用 Angular 4 方法?

azure - .net 7 隔离的 Azure 函数依赖注入(inject)在部署时失败(在本地工作)

java - 如何使用 Dagger 2 从多个独立组件注入(inject)父/子 Activity 的不同依赖项?