Проверка уникального свойства C # на бизнес-уровне - PullRequest
0 голосов
/ 06 сентября 2018

Я использую FluentValidation и PostSharp на своем бизнес-уровне. В моей базе данных есть таблица Admin , а столбец UserName в этой таблице является уникальным. Я хочу проверить уникальность с помощью « Aspect ». Мои коды следующие.

AdminValidator

public class AdminValidator : AbstractValidator<Admin>
{
    public AdminValidator(IEnumerable<Admin> admins)
    {
        RuleFor(x => x.Fullname).MaximumLength(50);
        RuleFor(x => x.Username).Matches(@"^\S{3,15}$").IsUnique(admins);
        RuleFor(x => x.Password).Matches(@"^\S{5,20}$");
    }
}

IsUnique метод расширения

public static class Extensions
{
    public static IRuleBuilderOptions<TItem, TProperty> IsUnique<TItem, TProperty>(
        this IRuleBuilder<TItem, TProperty> ruleBuilder, IEnumerable<TItem> items)
        where TItem : class
    {
        return ruleBuilder.SetValidator(new UniqueValidator<TItem>(items));
    }
}

public class UniqueValidator<T> : PropertyValidator
    where T : class
{
    private readonly IEnumerable<T> _items;

    public UniqueValidator(IEnumerable<T> items)
        : base("{PropertyName} must be unique")
    {
        _items = items;
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        var editedItem = context.Instance as T;
        var newValue = context.PropertyValue as string;
        var property = typeof(T).GetTypeInfo().GetDeclaredProperty(context.PropertyName);
        return _items.All(item =>
            item.Equals(editedItem) || property.GetValue(item).ToString() != newValue);
    }
}

Свободный аспект проверки

[Serializable]
public class FluentValidationAspect : OnMethodBoundaryAspect
{
    private readonly Type _validatorType;
    private readonly object[] _parameters;

    public FluentValidationAspect(Type validatorType, params object[] parameters)
    {
        _validatorType = validatorType;
        _parameters = parameters;
    }

    public override void OnEntry(MethodExecutionArgs args)
    {
        var validator = (IValidator)Activator.CreateInstance(_validatorType, _parameters);
        var entityType = _validatorType.BaseType?.GetGenericArguments()[0];
        var entities = args.Arguments.Where(x => x.GetType() == entityType);

        foreach (var entity in entities)
            ValidatorTool.FluentValidate(validator, entity);
    }
}

и AdminManager

public class AdminManager : IAdminService
{
    private readonly IAdminDal _adminDal;

    public AdminManager(IAdminDal adminDal)
    {
        _adminDal = adminDal;
    }

    public Admin GetByUsername(string username)
        => string.IsNullOrEmpty(username) ? null : _adminDal.Get(x => x.Username.Equals(username));

    [FluentValidationAspect(typeof(AdminValidator))]    // I need to pass IEnumerable<Admin> as a second parameter.
    public void Add(Admin admin) => _adminDal.Add(admin);

    [FluentValidationAspect(typeof(AdminValidator))]    // 
    public void Update(Admin admin) => _adminDal.Update(admin);

    public void DeleteById(int id) => _adminDal.Delete(new Admin { Id = id });
}

Как я уже упоминал в строке комментария, мне нужно передать IEnumerable в FluentValidationAspect. Но динамические параметры не могут быть переданы в атрибуты. В результате я заблокирован здесь. Как лучше всего проверить уникальность?

Заранее спасибо за помощь? С наилучшими пожеланиями ...

1 Ответ

0 голосов
/ 07 сентября 2018

Нельзя передавать динамические значения в атрибутах, поэтому вам придется выполнить проверку в теле метода.

public void Add(Admin admin)
{
    var admins = GetAll():
    var val = new AdminValidator(admins);

    validator.ValidateAndThrow(admin);
     _adminDal.Add(admin);


}
...