依赖关系注入和 C# 中的保护子句和空对象模式

本文关键字:子句 对象 模式 保护 关系 注入 依赖 | 更新日期: 2023-09-27 18:35:59

使用构造函数注入,依赖项被注入到这样的消费者中(至少我希望我理解正确):

public class SomeConsumer
{
    private IDependency someDependency;
    public SomeConsumer(IDependency someDependency)
    {
        if (someDependency != null)
        {
            this.someDependency = someDependency;
        }
        else
        {
            throw new ArgumentNullException("someDependency");
        }
    }
    public void Baz()
    {
        someDependency.DoSomething();
    }
    (...)
}

如果我使用 Null 对象模式进行 IDependency,我是否需要保护子句?还是注入空对象是错误的?

更新:为了澄清,让我们假设我有这样的类和接口:

public interface IDependency
{
    void DoSomething();
}
public class NullDependency : IDependency
{
    public void DoSomething()
    {
        //Do nothing...
    }
}
public class RealDependency : IDependency
{
    public void DoSomething()
    {
        Console.WriteLine("Did something");
    }
}
public class Foo
{
    public void Bar()
    {
        IDependency dependency = new NullDependency();
        SomeConsumer sc = new SomeConsumer(dependency);
        sc.Baz();
    }
}

然后,我是否可以安全地从 SomeConsumer 中删除保护子句,使其看起来像:

public class SomeConsumer
{
    private IDependency someDependency;
    public SomeConsumer(IDependency someDependency)
    {
        this.someDependency = someDependency;
    }
    public void Baz()
    {
        //if someDependency is a NullDependency, this does nothing
        someDependency.DoSomething(); 
    }
    (...)
}

还是我应该使用保护条款,因为我不能确定null永远不会被注入?

依赖关系注入和 C# 中的保护子句和空对象模式

恕我直言,在以下情况下,我会放弃保护条款:

  • SomeConsumer仅在您的产品中使用
  • 空对象模式完全由您的团队和/或依赖注入容器配置存在

我可能不会放弃保护条款,如果:

    对于
  • 目标受众来说,对空对象的需求没有充分记录
  • SomeConsumer 是开放 API 的一部分,供不知道空对象模式的开发人员使用
  • 我希望在依赖项注入容器实例化SomeConsumer时收到反馈,说明我犯了一个错误

我不喜欢在任何情况下删除保护条款。无论谁使用此类,创建的所有对象都应该有效。如果允许通过构造函数注入 null,则允许构造无效对象。稍后,当调用方法时,某些内容会中断。

这不是

这个类是否是内部的问题。问题是,在调用构造函数时,您是否确保在所有地方都采取所有措施来生成非 null 值?即使你的答案是"是",下一个问题是你为什么要浪费时间和精力来检查呢?

只要留下保护子句,你就会知道这个类的所有对象都将被正确构造。否则,如果您无意中将 null 传递给构造函数,一些完全不相关的类将失败,您将很难将错误追溯到此构造函数。

与此相关的是,一些保护条款(那些测试空以外的条件的子句)通常是重新考虑设计的原因。你可能会觉得这篇文章很有趣 - 为什么我们需要保护条款?

恕我直言,注入空对象是完全可以的,这在测试中经常使用。当我不关心这种依赖关系时,我经常在我的单元测试中注入具有默认行为的模拟。

我可能会用抛出异常或完全删除它来替换null检查。它目前不执行任何操作,因为 someDependency 变量的默认值无论如何都是null