简体   繁体   English

C# 在 setter 方法上添加验证

[英]C# add validation on a setter method

I have aa couple of variables that i define in C# by:我在 C# 中定义了几个变量:

public String firstName { get; set; }
public String lastName { get; set; }
public String organization { get; set; }

What i want is to add validation to these methods when you try to set a value.我想要的是在您尝试设置值时向这些方法添加验证。 Lets say your going to set a value for firstName, the i should pass thrue a regexp to actuelly be set, otherwise an exception should be thrown.假设你要为 firstName 设置一个值,我应该通过一个正则表达式来实际设置,否则应该抛出一个异常。 Is this possible to build with this "short syntax" or should I go for standard (like in JAVA) getters and setters and in there validate the data?这是否可以使用这种“短语法”构建,或者我应该 go 用于标准(如在 JAVA 中)getter 和 setter 并在那里验证数据?

If you want to validate when the property is set, you need to use non-auto properties (ie, manually defined get and set methods).如果要在设置属性时进行验证,则需要使用非自动属性(即手动定义的getset方法)。

But another way to validate is to have the validation logic separate from the domain object.但另一种验证方法是将验证逻辑与域 object 分开。

class Customer {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Organization { get; set; }
}

interface IValidator<T> {
    bool Validate(T t);
}

class CustomerValidator : IValidator<Customer> {
    public bool Validate(Customer t) {
        // validation logic
    }
}

Then, you could say:然后,你可以说:

Customer customer = // populate customer
var validator = new CustomerValidator();
if(!validator.Validate(customer)) {
    // head splode
}

This is the approach I prefer:这是我喜欢的方法:

  1. A Customer should not responsible for validating its own data, that is another responsibility and therefore should live elsewhere. Customer不应负责验证其自己的数据,这是另一项责任,因此应居住在其他地方。
  2. Different situations call for different validation logic for the same domain object.对于同一个域 object,不同的情况需要不同的验证逻辑。

What you have now are called "auto-properties," and only perform a simple "get/set".您现在拥有的称为“自动属性”,仅执行简单的“获取/设置”。 In order to customize the behavior of the get or set , you will need to convert the properties to field-backed properties:为了自定义getset的行为,您需要将属性转换为字段支持的属性:

private string _firstName;
public string FirstName 
{ 
    get {return _firstName;} 
    set 
    {
       Validate(value); _firstName = value;
    }
}

Note that I changed String to string and capitalized the property name, in following accepted C# naming best practices.请注意,我按照公认的 C# 命名最佳实践将String更改为string并将属性名称大写。

I wouldn't add validation in the setter at all.我根本不会在setter中添加验证。 Rather, I would create a function called validate instead...that way all your validation code is in one spot rather scattered throughout your setters .相反,我会创建一个名为validate的 function ......这样你的所有验证代码都在一个位置,而不是分散在你的setters中。

It's best practice to apply SRP.应用 SRP 是最佳实践。 Set the validation in a separate class.在单独的 class 中设置验证。

You can use FluentValidation您可以使用FluentValidation

       Install-Package FluentValidation

You would define a set of validation rules for Customer class by inheriting from AbstractValidator<Customer> :您可以通过继承AbstractValidator<Customer>为客户 class 定义一组验证规则:

Example:例子:

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

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

To run the validator, instantiate the validator object and call the Validate method, passing in the object to validate.要运行验证器,请实例化验证器 object 并调用 Validate 方法,传入 object 进行验证。

   Customer customer = new Customer();
   CustomerValidator validator = new CustomerValidator();

   ValidationResult result = validator.Validate(customer);

 if(! results.IsValid) {
   foreach(var failure in results.Errors) {
       Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);

} } } }

You have to use the full property syntax for this.您必须为此使用完整的属性语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM