gpt4 book ai didi

c# - 控制反转如何帮助我?

转载 作者:行者123 更新时间:2023-11-30 22:30:06 25 4
gpt4 key购买 nike

我正在尝试了解控制反转以及它如何帮助我进行单元测试。我已经阅读了一些关于 IOC 及其作用的在线解释,但我不太了解它。

我开发了一个示例项目,其中包括使用 StructureMap 进行单元测试。 StructureMap 设置代码如下:

private readonly IAccountRepository _accountRepository

public Logon()
{
_accountRepository = ObjectFactory.GetInstance<IAccountRepository>();
}

不过,我不明白的是,正如我所见,我可以简单地将上述内容声明为以下内容:
AccountRepository _accountRepository = new AccountRepository();

它会和之前的代码做同样的事情。所以,我只是想知道是否有人可以帮助我以简单的方式向我解释使用 IOC 的好处是什么(尤其是在处理单元测试时)。

谢谢

最佳答案

Inversion of Control是让框架回调到用户代码的概念。这是一个非常抽象的概念,它只是描述了库和框架之间的区别,或者可以将其描述为“定义框架的特征”。一个库被我们的代码调用,而一个框架控制着我们的代码。任何框架都提供了允许我们插入代码的钩子(Hook)。

控制反转是一种模式,只有在构建框架时您是框架开发人员,或者当您是与框架代码交互的应用程序开发人员时,才能应用该模式。但是当专门使用应用程序代码时,IoC 不适用。

依赖抽象而不是实现的行为称为依赖倒置,应用程序和框架开发人员都可以实践依赖倒置。所以你所说的 IoC 实际上是依赖倒置,正如 Krzysztof 已经评论过的:你所做的不是 IoC。从现在开始我将讨论依赖倒置。

依赖倒置基本上有两种形式/实现:服务定位器和依赖注入(inject)。

服务定位器模式 ,您从需要依赖项的类中调用静态工厂。一般来说,它看起来像这样:

public class Service
{
public void SomeOperation() {
IDependency dependency =
ServiceLocator.GetInstance<IDependency>();
dependency.Execute();
}
}

这个例子对你来说应该很熟悉,因为这就是你在 Logon 中所做的。方法:您正在使用服务定位器模式。

依赖注入(inject)模式 ,从外部注入(inject)一个类需要的所有依赖项;最好使用构造函数。类本身不负责获取其依赖项。该职责向上移动到调用堆栈。使用依赖注入(inject)时,上一个类将如下所示:
public class Service
{
private readonly IDependency dependency;

public Service(IDependency dependency)

{
this.dependency = 依赖;
}
    public void SomeOperation()

{
this.dependency.Execute();
}
}

这两种模式都是依赖倒置,因为在这两种情况下 Service class 不负责创建依赖项,也不知道它使用的是哪个实现。它只是与接口(interface)对话。这两种模式都为您提供了对类正在使用的实现的灵活性,从而允许您编写更灵活的软件。

然而,Service Locator 模式存在许多问题,这就是它被视为反模式的原因。您已经遇到了这些问题,因为您想知道依赖倒置(在您的情况下是服务定位器)如何帮助您进行单元测试。

答案是服务定位器模式对单元测试没有帮助。相反:它使单元测试变得非常困难。通过让类(class)拨打 ObjectFactory ,您在两者之间创建了硬依赖关系。更换 IAccountRepository对于测试,也意味着您的单元测试必须使用 ObjectFactory .这会使您的单元测试更难阅读。但更重要的是,自从 ObjectFactory是一个静态实例,所有单元测试都使用同一个实例,这使得很难单独运行测试并在每个测试的基础上交换实现。

我过去使用了服务定位器模式,我处理这个问题的方式是在我的服务定位器中注册依赖项,我可以逐个线程地更改这些依赖项(使用幕后的 [ThreadStatic] 字段)。这允许我并行运行我的测试(默认情况下 MSTest 所做的)同时保持测试隔离。然而,这样做的问题是,这会很快变得复杂,用各种技术性的东西把测试弄得一团糟,这让我花了很多时间来解决这些技术问题,而我本来可以编写更多的测试。

这些问题的真正解决方案是依赖注入(inject)。一旦您通过其构造函数注入(inject)类所需的依赖项,所有这些问题都会消失。这不仅使类需要什么依赖项(没有隐藏的依赖项)变得非常清楚,而且每个单元测试本身都负责注入(inject)它需要的依赖项。这使得编写测试变得更加容易,并防止您在单元测试中配置 DI 容器。

进一步阅读: Service Locator is an Anti-Pattern .

关于c# - 控制反转如何帮助我?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9857928/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com