C # добавить проверку в метод установки

#c# #properties #setter #getter

#c# #свойства #установщик #средство получения

Вопрос:

У меня есть пара переменных, которые я определяю в C # с помощью:

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

Что я хочу, так это добавить проверку к этим методам при попытке установить значение. Допустим, вы собираетесь установить значение для FirstName, i должен пройти через регулярное выражение, чтобы оно действительно было установлено, в противном случае должно быть выдано исключение. Возможно ли это построить с помощью этого «короткого синтаксиса» или я должен использовать стандартные (например, в JAVA) средства получения и установки и там проверять данные?

Ответ №1:

Если вы хотите проверять, когда свойство установлено, вам необходимо использовать неавтоматические свойства (т. Е. определенные вручную get и set методы).

Но другой способ проверки — отделить логику проверки от объекта домена.

 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
    }
}
  

Тогда вы могли бы сказать:

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

Это подход, который я предпочитаю:

  1. A Customer не должен отвечать за проверку своих собственных данных, это другая ответственность, и поэтому он должен находиться в другом месте.
  2. В разных ситуациях требуется разная логика проверки для одного и того же объекта домена.

Комментарии:

1. Я не согласен, даже если ваша проверка завершается неудачей, данные вашего клиента недействительны. Что помешает ему записывать мусор в базу данных, если вы испортите внешнюю проверку?

2. @Blindy: Ваш уровень сохраняемости должен быть подключен к средствам проверки, которые не сохраняются, если проверка завершается неудачей.

3. Клиент @Blindy не должен нести ответственность за запись в базу данных. Это было бы еще одной ответственностью, которую клиент не должен нести.

4. Я понимаю «Принцип единой ответственности» (SRP), но мне всегда интересно, где должно быть «ограничение». Это означает, что вы могли бы зайти слишком далеко… например, создать класс для установки свойств (для вас). Я ничего не говорю о вашем примере… Кажется, я просто задаюсь вопросом: «Как далеко я должен зайти в применении SRP»? … может быть, я должен задать это как вопрос?

5. @Prisoner ZERO: Я думаю, что это хорошая основа для другого вопроса, но вам нужно будет привести конкретный пример, чтобы сделать его более определенным.

Ответ №2:

То, что у вас есть сейчас, называется «авто-свойства» и выполняет только простое «получение / установка». Чтобы настроить поведение get или set , вам нужно будет преобразовать свойства в свойства, поддерживаемые полями:

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

Обратите внимание, что я изменил String на string и написал имя свойства с заглавной буквы, следуя принятым в C # рекомендациям по именованию.

Ответ №3:

Я бы вообще не добавлял проверку в setter . Вместо этого я бы создал функцию, вызываемую validate …таким образом, весь ваш код проверки находится в одном месте, а не разбросан по всему вашему setters .

Ответ №4:

Наилучшей практикой является применение SRP. Установите проверку в отдельном классе.

Вы можете использовать FluentValidation

        Install-Package FluentValidation
  

Вы бы определили набор правил проверки для класса Customer путем наследования от AbstractValidator<Customer> :

Пример:

   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
    }
  }
  

Чтобы запустить средство проверки, создайте экземпляр объекта validator и вызовите метод Validate, передав объект для проверки.

    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);
  

}
}

Комментарии:

1. Где появляется сообщение, полученное в результате проверки?

2. Сообщение может быть частью правила, например, RuleFor(x => x.Forename).NotEmpty().WithMessage("Please specify a first name");

Ответ №5:

Для этого вы должны использовать полный синтаксис свойств.