依赖关系注入和 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
永远不会被注入?
恕我直言,在以下情况下,我会放弃保护条款:
-
SomeConsumer
仅在您的产品中使用 - 空对象模式完全由您的团队和/或依赖注入容器配置存在
我可能不会放弃保护条款,如果:
- 对于
- 目标受众来说,对空对象的需求没有充分记录
-
SomeConsumer
是开放 API 的一部分,供不知道空对象模式的开发人员使用 - 我希望在依赖项注入容器实例化
SomeConsumer
时收到反馈,说明我犯了一个错误
我不喜欢在任何情况下删除保护条款。无论谁使用此类,创建的所有对象都应该有效。如果允许通过构造函数注入 null,则允许构造无效对象。稍后,当调用方法时,某些内容会中断。
这不是这个类是否是内部的问题。问题是,在调用构造函数时,您是否确保在所有地方都采取所有措施来生成非 null 值?即使你的答案是"是",下一个问题是你为什么要浪费时间和精力来检查呢?
只要留下保护子句,你就会知道这个类的所有对象都将被正确构造。否则,如果您无意中将 null 传递给构造函数,一些完全不相关的类将失败,您将很难将错误追溯到此构造函数。
与此相关的是,一些保护条款(那些测试空以外的条件的子句)通常是重新考虑设计的原因。你可能会觉得这篇文章很有趣 - 为什么我们需要保护条款?
恕我直言,注入空对象是完全可以的,这在测试中经常使用。当我不关心这种依赖关系时,我经常在我的单元测试中注入具有默认行为的模拟。
我可能会用抛出异常或完全删除它来替换null
检查。它目前不执行任何操作,因为 someDependency
变量的默认值无论如何都是null
。