#c# #.net #refactoring #dry #fluentvalidation
#c# #.net #рефакторинг #dry #плавная проверка
Вопрос:
У меня есть несколько классов моделей, и я заметил, что Name
свойство (например: название страны, имя_ ветви, имя_статьи и т.д.) Имеет одинаковое правило во всем приложении, например, оно должно быть обязательным и не может превышать определенного количества символов. В следующем примере BranchAddClass.cs
.
Вопрос:
- Как определить пользовательский объект и повторно использовать в
Model Class
коде вместо объявления в виде строки (см.BranchName
Свойство вBranchAddModel.cs
). - Как реализовать
FluentValidation
правила в файле nameField.cs. На данный момент проверка повторяется (см.BranchAddModel.cs
Класс).
nameField.cs
Я думал создать класс object и выполнить проверку в этом классе, чтобы не нарушать DRY
принцип. Но я не могу этого достичь. Если у вас есть лучший способ реализовать то, чего я пытаюсь достичь, я бы приветствовал!
public class NameField
{
private readonly string _value;
private NameField(string value)
{
_value = value;
}
}
Если класс nameField работает, то я надеюсь, что смогу использовать его в остальной части приложения, см. Пример
BranchAddModel.cs
namespace Application
{
[Validator(typeof(BranchAddModelValidator))]
public class BranchAddModel
{
public byte ServiceTypeId { get; set; }
public string BranchName { get; set; } //this could be replaced when NameField issue is solved.
public NameField PreferredBranchName { get; set; } //Reference to NameField class
public short BaseCurrencyId { get; set; }
public short TimezoneId { get; set; }
}
public class BranchAddModelValidator : AbstractValidator<BranchAddModel>
{
public BranchAddModelValidator()
{
//trying to avoid writing this validation.
RuleFor(x => x.BranchName)
.NotEmpty()
.Length(0, 128);
RuleFor(x => x.ServiceTypeId)
.NotEmpty();
RuleFor(x => x.BaseCurrencyId)
.NotEmpty();
RuleFor(x => x.TimezoneId)
.NotEmpty();
}
}
}
Примечание: Если вы считаете, что вопрос неясен, пожалуйста, дайте мне знать.
Комментарии:
1. Используйте отражение для построения дерева выражений для передачи в
RuleFor
2. @Rob Не могли бы вы, пожалуйста, привести пример?
Ответ №1:
Я бы попробовал использовать дженерики. Таким образом, вы можете легко добавить его в другие модели и свойства (countryName, StateName).
public class BranchAddModelValidator : AbstractValidator<BranchAddModel>
{
public BranchAddModelValidator()
{
this.AddDefaultNameValidation(x => x.BranchName);
RuleFor(x => x.ServiceTypeId)
.NotEmpty();
RuleFor(x => x.BaseCurrencyId)
.NotEmpty();
RuleFor(x => x.TimezoneId)
.NotEmpty();
}
}
public static class AbstractValidatorExtensions
{
public static void AddDefaultNameValidation<T>(this AbstractValidator<T> validator, Expression<Func<T, string>> property)
{
validator.RuleFor(property)
.NotEmpty()
.Length(0, 128);
}
}
ПРИМЕЧАНИЕ: Он компилируется, но я не проверял, работает ли проверка на самом деле. Пакет Fluent Validation для меня новый, и сейчас у меня нет времени его изучать, но, похоже, стоит запомнить.
Ответ №2:
Вместо того, чтобы оборачивать класс, вы можете сделать что-то вроде этого:
var param = Expression.Parameter(typeof(BranchAddModel));
var items = typeof(BranchAddModel).GetProperties()
.Where(p => p.PropertyType == typeof(string))
.Select(r => Expression.Lambda<Func<BranchAddModel, string>>(Expression.PropertyOrField(param, r.Name), param));
foreach (var item in items)
{
RuleFor(item)
.NotEmpty()
.Length(0, 128);
}
Который создаст перечислимый из Expression<Func<BranchAddModel, string>>
, который вы можете затем перебирать и передавать в RuleFor