传递Lambda表达式而不是Object的优点

时间:2012-08-23 17:49:01

标签: c# lambda fluentvalidation

我一直在审查FluentValidation这是一个很好的验证库,但我注意到它们传递LambdaExpression而不是对象属性,我想了解这种用法​​的优点:

using FluentValidation;

public class CustomerValidator: AbstractValidator<Customer> {
  public CustomerValidator() {
    RuleFor(customer => customer.Surname).NotEmpty();
    RuleFor(customer => customer.Forename).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(customer => customer.Company).NotNull();
    RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
    RuleFor(customer => customer.Address).Length(20, 250);
    RuleFor(customer => customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode");
  }

  private bool BeAValidPostcode(string postcode) {
    // custom postcode validating logic goes here
  }
}

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);

bool validationSucceeded = results.IsValid;
IList<ValidationFailure> failures = results.Errors;

正如您所看到的那样RuleFor(customer => customer.Surname).NotEmpty();RuleFor(customer.Surname).NotEmpty();还不够干净?

2 个答案:

答案 0 :(得分:6)

  

相反,RuleFor(customer.Surname).NotEmpty();不够干净?

没有。因为在您致电RuleFor时,您没有客户 - 因此您无法访问他们的姓氏。

与代理人通常的情况一样,你传递代码以便稍后执行。表达式customer.Surname是一个表达式,它将在现有customer变量的上下文中立即进行评估

现在,如果我们拥有神秘的infoof运算符,我们可以执行此操作而无需创建委托。我们可以写一些类似的东西:

RuleFor(infoof(Customer.Surname)).NotEmpty()

哪个会很可爱。 RuleFor方法将采用该属性引用,并在以后针对给定客户对其进行评估。精彩。

不幸的是,我们没有那个运营商 - 所以表达“当你有一个客户,获得Surname财产”的想法的最简单方法是使用代表。它也非常灵活,因为它可以(几乎)使用你想要执行的任何代码。

答案 1 :(得分:1)

如果您要传递customer.SurName,则会指向特定SurName实例的customer属性的值。使用lambda函数允许验证逻辑在调用验证逻辑时获取客户对象,然后检索 客户的SurName属性。