【问题标题】:With an IoC container, should a constructor still check if a parameter is null?对于 IoC 容器,构造函数是否仍应检查参数是否为空?
【发布时间】:2013-08-20 04:14:55
【问题描述】:

我正在查看 Orchard CMS 项目的源代码,我注意到他们的一些构造函数从未验证所需的参数不为空。起初,我认为这很奇怪。我问自己,“考虑到你说这个依赖是必需的,你不想检查你是否真的有一个吗?”意识到该项目使用 Castle Windsor 作为 IoC 容器,我后来想,“好吧,当容器试图找到具有需求的对象的依赖项时,它会抛出异常。”所以我的问题是,当我知道 IoC 容器会为我检查时,我还应该检查吗?

或者双重检查是好的,因为从某种意义上说,我坚持反向封装原则:“我不知道我是如何获得这种依赖关系的,但我真的需要一个!”

【问题讨论】:

  • 这是 Mark Seemann 关于这个主题的一篇有趣的文章:blog.ploeh.dk/2013/07/08/defensive-coding
  • 谢谢你....我已经成为马克的粉丝了。我一直说你应该在处理之前检查方法的要求,因为它可以在遇到问题时更容易地进行故障排除。
  • 说实话,现在我不再检查由容器连接的类的构造函数参数了。我知道我的容器(和大多数容器)永远不会允许将 null 注入构造函数。因此,在这种情况下省略检查是安全的,并使代码更易读、更易于维护。

标签: c# design-patterns ioc-container


【解决方案1】:

我被引导遵循检查每个可见参数是否为 NULL 的做法,而不管它是如何被设计为实例化的。总有可能有人会选择不同的 IoC 容器来执行更宽松的类型委托策略,或者一些初级开发人员找到您的代码并希望它能够按照他们想要的方式工作。

不管怎样,安全总比后悔好。在这种情况下,最好花几秒钟来保护代码,然后再花几个小时来保护代码。

【讨论】:

  • 这也是我一直以来的想法。但是这种情况让我意识到,在我的所有生产代码中,我从来没有因为 IoC 容器而在构造函数中抛出 ArgumentNullException。我的代码中似乎有额外的噪音。
【解决方案2】:

我不会检查。我认为这会不必要地使您的构造函数混乱。

如果您的 DI 容器没有所需的依赖项,您的手动或自动测试应该很快就会发现这一点。

通过将某些东西作为构造函数的参数,您是在说它是必需的。

另外,如果你以某种方式得到一个空参数,你会怎么做?

构造函数是否尝试构造一个新的 null 类型?可能不是因为这个构造函数不知道传入的类型需要实例化自己。

此时您应该只捕获异常并优雅地退出或继续前进;但无论如何你应该有这种情况的代码。

【讨论】:

  • 只是扮演魔鬼的拥护者......在解决问题时,ArgumentNullException 与 NullReferenceException 相比不是更能说明问题吗?
  • 与很多编程一样,我认为我们处于偏好领域。
  • 方法越小,获得NullReferenceException 就越少,因为越容易发现哪个引用为空:-)
【解决方案3】:

是的。类设计必须不知道其依赖项是如何注入的,并且必须始终保护其不变量。

【讨论】:

    【解决方案4】:

    最新版本的 Ninject 和 Structure map 在你进入构造函数之前都会抛出一个绑定异常。 因此,在构造函数中检查参数 null 异常无论如何都无济于事。

    所以我投票赞成保持你的代码干净。

    我并不是说防御性代码没有位置,但如果您使用现代 IoC,则构造函数检查不是一个位置。

    虽然将来总有可能有人会选择不强制执行严格类型委派策略的不同 IoC 容器。我觉得这是一个“假设”的论点,改变 IoC 是一个相当大的架构决策,个人而言,自动生成空检查的成本可能不会太大。

    对我来说,有人进来并需要阅读您的代码的可能性要高得多。更容易阅读的代码通常不太可能出现错误,并且维护起来也更快。

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      相关资源
      最近更新 更多