您会选择什么,轻微的性能损失或一些额外的复杂性?

时间:2011-01-04 09:12:23

标签: c# validation expression-trees

我们正在使用验证框架(我们自己编写的东西),它允许我们对对象进行验证断言。

string Validation<T,U>(T obj, Func<T,U> selector, Validations.IsNotNull,
                       string failureMessage) 
       {
           var propertyToBeValidated = selector(obj);
           // Do validation here, if it fails, return failure message
       }

问题在于:

  • 该消息是强制性的。我们无法自动生成查看选择器的有意义的消息。

另一种选择是将上述方法的签名更改为:

string Validation<T,U>(T obj, Expression<Func<T,U>> selector, 
                       Validations.IsNotNull, string failureMessage = null) 

在这种情况下,失败消息是可选的,我们可以从表达式树中获取属性名称。

但是,这需要在调用选择器之前使用Expression.Compile并将事情减慢3个数量级。截至目前,消息是强制性的,但由于验证在其他地方,重构也需要更改验证消息。

你会建议什么:

  • 更改签名并接受表达式。如果需要,缓存已编译的表达式并自动生成消息。是否提供了消息,而是使用该消息。
  • 由于您拥有良好的测试覆盖率,因此手动更改消息是可接受的开销。保留签名,避免额外的复杂性和性能损失。

编辑:我们正在使用这个跨多层的验证框架。在用于验证输入参数的输出控制器中,在用于验证传入请求的服务中以及在用于验证某些操作之后的对象状态的集成测试中。表达的成本。与其中一些成本相比,编译是微不足道的,但与数据库访问等相比并不是微不足道的。 感谢

3 个答案:

答案 0 :(得分:2)

你为什么要选择?你可以同时拥有两个

string Validation<T,U>(T obj, Func<T,U> selector, Validations.IsNotNull,
                        string failureMessage)

string Validation<T,U>(T obj, Expression<Func<T,U>> selector,
                          Validations.IsNotNull)

作为重载。这样,只有在没有消息的情况下才能获取perf命中,并且无法缓存已编译的lambda。

答案 1 :(得分:0)

嗯,我认为将此与db调用进行比较就像比较苹果和橙子一样。而且每个对象很可能会多次调用这个代码,想象一个用这个参数装饰的类,私有成员,以及在for循环中创建的这种类型的对象:D..hope我说的是有意义的,因为我没有真正用泛型或编译表达式等进行任何编码。但是我猜你做的是尝试通过分析表达式树来猜测得到验证的东西。

就个人而言,我认为最好保持信息的强制性,如果没有提供消息,那么提供两个单独的方法(多态)的可能性如何得到充分记录的警告......

答案 2 :(得分:0)

我们得出结论,对我们来说,使用表达式最有意义。 DB和WS调用的开销远大于此。