16

オブジェクトに複数のバリデータを追加できますか? 例えば:

public interface IFoo
{
    int Id { get; set; }
    string Name { get; set; }
}

public interface IBar
{
    string Stuff { get; set; }
}

public class FooValidator : AbstractValidator<IFoo>
{
    public FooValidator ()
    {
        RuleFor(x => x.Id).NotEmpty().GreaterThan(0);
    }
}

public class BarValidator : AbstractValidator<IBar>
{
    public BarValidator()
    {
        RuleFor(x => x.Stuff).Length(5, 30);
    }
}

public class FooBar : IFoo, IBar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Stuff { get; set; }
}

public class FooBarValidator : AbstractValidator<FooBar>
{
    public FooBarValidator()
    {
        RuleFor(x => x)
            .SetValidator(new FooValidator())
            .SetValidator(new BarValidator());
    }
}

テストを実行しています。

FooBarValidator validator = new FooBarValidator();
validator.ShouldHaveValidationErrorFor(x => x.Id, 0);

私は得るInvalidOperationException

式 x => x のプロパティ名を自動的に決定できませんでした。「WithName」を呼び出してカスタム プロパティ名を指定してください。

これを実装する方法はありますか、それとも意図しない方法で FluentValidation を使用しようとしていますか?

4

4 に答える 4

22

RuleFor はプロパティ レベルのルールを作成しようとしています。さらに AddRule 関数を使用して、汎用ルールを追加できます。

これを使用して、複合ルールの概念実証を作成しました。他のバリデータのセットを取り込んで実行します。コードはからyield break直接取得しました。どうすればいいのかわからなかったので、ソースから取得しました。私はその完全な目的をたどりませんでしたが、すべてがそのまま機能しているようです:)FluentValidatorDelegateValidator

コード

public interface IFoo
{
    int Id { get; set; }
    string Name { get; set; }
}

public interface IBar
{
    string Stuff { get; set; }
}

public class FooValidator : AbstractValidator<IFoo>
{
    public FooValidator()
    {
        RuleFor(x => x.Id).NotEmpty().GreaterThan(0);
    }
}

public class BarValidator : AbstractValidator<IBar>
{
    public BarValidator()
    {
        RuleFor(x => x.Stuff).Length(5, 30);
    }
}

public class FooBar : IFoo, IBar
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Stuff { get; set; }
}

public class CompositeValidatorRule : IValidationRule
{
    private IValidator[] _validators;

    public CompositeValidatorRule(params IValidator[] validators)
    {
        _validators = validators;
    }

    #region IValidationRule Members
    public string RuleSet
    {
        get; set;
    }

    public IEnumerable<ServiceStack.FluentValidation.Results.ValidationFailure> Validate(ValidationContext context)
    {
        var ret = new List<ServiceStack.FluentValidation.Results.ValidationFailure>();

        foreach(var v in _validators)
        {
            ret.AddRange(v.Validate(context).Errors);
        }

        return ret;
    }

    public IEnumerable<ServiceStack.FluentValidation.Validators.IPropertyValidator> Validators
    {
        get { yield break; }
    }
    #endregion
}

public class FooBarValidator : AbstractValidator<FooBar>
{
    public FooBarValidator()
    {
        AddRule(new CompositeValidatorRule(new FooValidator(), new BarValidator()));
    }
}

ベース テスト ケース:

    [TestMethod]
    public void TestValidator()
    {
        FooBarValidator validator = new FooBarValidator();
        var result = validator.Validate(new FooBar());

    }

これが役立つことを願っています。

于 2012-11-02T17:52:14.087 に答える
1

RuleSets を使用して、さまざまなタイプの検証を適用できます。それがあなたがしようとしていることに役立つ場合:

FluentValidation ルールセット

于 2012-11-02T15:41:48.800 に答える