【问题标题】:How can I use DI to provide a validator to an entity via IValidatableObject interface?如何使用 DI 通过 IValidatableObject 接口向实体提供验证器?
【发布时间】:2013-03-27 08:21:23
【问题描述】:

我的业务层有实现 IValidatableObject 的对象。我希望这些实体在外部程序集中的业务规则,然后调用类型的验证器:

public IEnumerable<ValidationResult> Validate(ValidationContext vc){}

我打算使用 DI 将验证器注入到实现 IValidatableObject 接口的类型的构造函数中。

   public Customer(ICustomerValidator validator)
        {
            this.Validator = validator;
        }

我想我会在类型工厂中调用 Unity 并从那里注入。

但是很多时候实体只是读取而不是修改,即客户实体。它并不总是需要一个验证器,因为它可能只是用来支持一个用例,而实际上并没有被它修改。

所以我想我可以:

  1. 创建 CustomerEdit 类,然后仅在这些类上使用构造函数注入器,而不是在说 CustomerRead 类上,但这会导致类爆炸,而我并不真正希望此应用程序。
  2. 拥有一个客户类并在需要时注入验证器。

对于上面的 2 中 IValidatableObject 接口的实现的 Validate 方法似乎是合适的地方。问题是在很多情况下,这个方法是由我自己的代码以外的代码调用的。例如,来自实体框架和某些类型,来自 MVC,因为它们将用作模型类。

所以现在我不得不重写框架代码中的方法,这样我才能进行 DI。这“似乎”不正确,但老实说我不知道​​为什么。

接下来我看的是 ValidationContext 的 GetService() 方法。

public IEnumerable<ValidationResult> Validate(ValidationContext vc)
{

var customerValidator = (ICustomerValidator)vc.GetService(typeof(ICustomerValidator));
return customerValidator.Validate();

}

但如果我开始这样做,我不是刚刚踏入了ServiceLocator反模式的整个领域,打破了Demeter法则,让测试变得完全痛苦吗?

那么有没有更清洁的方法来解决这个问题,还是只是从我概述的内容中选择我的权衡?

【问题讨论】:

标签: c# .net validation dependency-injection


【解决方案1】:

最重要的原则:KISS.

因此,除非您要创建 10000 个业务对象,否则不要打扰,并始终注入您的验证服务。

如果这样做会降低性能,请在需要时将类拆分为读取/编辑模型。

【讨论】:

  • 你认为过度工程?是的,你可能是对的。我确实考虑过这一点,但后来我想我会四处打听,因为有 KISS,然后有无知......而且其中一些东西对我来说很新。 ;)
  • 只要你有清晰的关注点分离和单元测试,重构应该不会很痛苦。
【解决方案2】:

关于这个问题的 Stevens cmets 让我找到了几篇与我的问题相关的博客文章。

这些博客文章的要点是,当注入的依赖项仅“在某些时候使用”时,构造函数注入被过度使用,但是通过将依赖项包含在构造函数中,我们使其“始终需要”。

在本文中,所描述的依赖项是 OrderShipper,但根据我的问题,它可以很容易地成为验证器。

所以开始

Constructor over-injection anti-pattern - Jeffrey Palermo

这里反驳

Rebuttal: Constructor over-injection anti-pattern by Mark Seemann

然后在这里进一步细化反驳:

Enabling DI for Lazy Components by Mark Seemann

除了接受答案之外,如果我真的想重新设计我的设计:将验证器注入到域类中,那么我可以注入一个 AbstractFactory。

与往常一样,当依赖项的生命周期可能比 消费者,解决方案是注入(通过构造函数!)一个抽象 工厂 - 马克·西曼

【讨论】:

    猜你喜欢
    • 2019-11-24
    • 2014-03-28
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    相关资源
    最近更新 更多