web-dev-qa-db-ja.com

クラスの階層のC#FluentValidation

データクラスの階層があります

public class Base
{
    // Fields to be validated
}

public class Derived1 : Base
{
    // More fields to be validated
}

public class Derived2 : Base
{
    // More fields to be validated
}

Baseクラスのフィールドのルールを複製せずにFluentValidationフレームワークを使用してDerived1とDerived2を検証する適切な方法は何でしょうか?

42
Nikolay Nahimov

取るべきアプローチの1つは次のとおりです。

public class Base
{
    public string BaseName { get; set; } 
}

public class Derived1 : Base
{
    public string Derived1Name { get; set; }
}

public class BaseValidator<T> : AbstractValidator<T> where T : Base
{
    public BaseValidator()
    {
        RuleFor(b => b.BaseName).NotNull();
    }
}

public class Derived1Validator : BaseValidator<Derived1>
{
    public Derived1Validator()
    {
        RuleFor(d => d.Derived1Name).NotNull();
    }
}

したがって、最初にベースバリデータを作成し、ジェネリック型の引数を受け入れ、ジェネリック型がbase型である必要があることを指定します。基本クラスの一般的なルールを設定して先に進みます。

基本クラスの子を検証するバリデーターの場合、これらのバリデーターはbaseValidatorから継承します。Tは派生クラス型です。

49
Yannick Meeus
public class Derived2Validator : AbstractValidator<Derived2>
{
    public Derived2Validator()
    {
        Include(new BaseValidator());
        Include(new Derived2Validator());
        RuleFor(d => d.Derived1Name).NotNull();
    }
}

Derived2ValidatorBaseValidatorまたはDerived1Validatorを継承する必要はありません。 Includeメソッドには、ベースバリデーターからのルールが含まれます。

56
Mohsin Syed

Include()メソッドを試しましたが、.netコアのswaggerによって生成されたモデルには変更が表示されなかったため、望ましい結果が得られませんでした。動作したのは、基本クラスを持つバリデーターから継承する新しいクラスを作成することでした

/// <summary>
/// Base Class for entity validator classes that specifies a base validator class
/// </summary>
/// <typeparam name="T">The Type being validated</typeparam>
/// <typeparam name="TBaseClass">The validater assigned to the base type of the type being validated</typeparam>
public abstract class BaseAbstractValidator<T, TBaseClass> : AbstractValidator<T>
    where TBaseClass : IEnumerable<IValidationRule>
{
    protected BaseAbstractValidator() => AppendRules<TBaseClass>();

    /// <summary>
    /// Add the set of validation rules
    /// </summary>
    /// <typeparam name="TValidationRule"></typeparam>
    private void AppendRules<TValidationRule>() where TValidationRule : IEnumerable<IValidationRule>
    {
        var rules = (IEnumerable<IValidationRule>)Activator.CreateInstance<TValidationRule>();
        foreach (var rule in rules)
        {
            AddRule(rule);
        }
    }
}
0
jonmeyer