C# 依赖注入和C语言中的Guard子句和Null对象模式#
使用构造函数注入,依赖项会像这样注入到消费者(至少我希望我能正确理解它): 如果我要为IDependency使用Null对象模式,我需要guard子句吗?或者注入空对象是错误的 更新: 为了澄清,我们假设我有如下类和接口:C# 依赖注入和C语言中的Guard子句和Null对象模式#,c#,dependency-injection,null-object-pattern,C#,Dependency Injection,Null Object Pattern,使用构造函数注入,依赖项会像这样注入到消费者(至少我希望我能正确理解它): 如果我要为IDependency使用Null对象模式,我需要guard子句吗?或者注入空对象是错误的 更新: 为了澄清,我们假设我有如下类和接口: public interface IDependency { void DoSomething(); } public class NullDependency : IDependency { public void DoSomething() {
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();
}
}
然后我是否可以安全地从某个消费者中删除guard子句,使其看起来像:
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();
}
(...)
}
或者我应该使用guard子句,因为我不能确定
null
永远不会被注入?我认为注入null对象是完全正确的,这在测试中经常使用。当我不关心依赖性时,我经常在单元测试中使用默认行为注入mock
我可能会将
null
检查替换为抛出异常或将其全部删除。由于someDependency
变量的默认值是null
,因此它当前不做任何事情 在以下情况下,我会放弃保护条款:
仅在您的产品中使用SomeConsumer
- 空对象模式完全由您的团队和/或依赖项注入容器配置实现
- 对于目标受众而言,没有充分记录对空对象的需求
是开放API的一部分,供不知道空对象模式的开发人员使用SomeConsumer
- 我希望在依赖项注入容器实例化
时收到它的反馈,指出我犯了错误SomeConsumer
- 在任何情况下,我都不喜欢放弃保护条款。无论谁使用这个类,创建的所有对象都应该是有效的。如果允许通过构造函数注入null,则允许构造无效对象。稍后,当调用一个方法时,会出现一些问题
这不是这个类是否是内部类的问题。问题是,在调用构造函数时,您是否会确保在所有地方都采取了所有措施来生成非空值?即使你的答案是“是”,下一个问题是你为什么要浪费时间和精力去检查
只需保留guard子句,您就会知道该类的所有对象都将被正确构造。否则,如果您无意中将null传递给构造函数,则一些完全不相关的类将失败,并且您将很难将错误追溯到此构造函数
另一个相关的注意事项是,一些保护条款(测试非空条件的条款)通常是重新考虑设计的原因。您可能会发现本文很有趣-我忘了添加引发的异常,问题已更新。使用比插入
null
对象指针要好得多。这样,您就不必通过null
检查使类复杂化。
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();
}
(...)
}