2

ドメイン オブジェクトであるデータソースをカプセル化する ViewModel があります。ドメインには、ドメインで定義されている検証ルールがありますが、ユーザーに情報を提供するために ViewModel によって再利用されます。

ビューモデル:

internal class RatedValuesViewModel : FluentDataErrorInfo
{
    public RatedValuesViewModel()
        : base(new RatedValuesViewModelValidator())
    {
    }

    public RatedValues DataSource { get; set; }

    ...
}

ドメイン オブジェクト:

class RatedValues
{
    public double? Head
    {
        get; set;
    }

    public double? DeltaPressure
    {
        get; set;
    }

    ...
}

これから実行する操作のコンテキストにおけるドメイン オブジェクト ルールは次のとおりです。

class GeneratePlotPumpCurvesRatedValuesValidationRules : AbstractValidator<RatedValues>
{
    public GeneratePlotPumpCurvesRatedValuesValidationRules()
    {
        Custom(itemToValidate => !AtLeastOneParameterSpecified(itemToValidate) ? new ValidationFailure(string.Empty, "You must specify at least one rated value.") : null);

        RuleFor(item => item.Head).Must(head => head == null).When(item => item.DeltaPressure != null).WithMessage("You can not specify both head and delta pressure.");
        RuleFor(item => item.DeltaPressure).Must(dp => dp == null).When(item => item.Head != null).WithMessage("You can not specify both head and delta pressure.");
    }

...
}

最後に: ドメイン内の検証ルールを再利用するビュー モデルの検証ルール:

class RatedValuesViewModelValidator : AbstractValidator<RatedValuesViewModel>
{
    private readonly GeneratePlotPumpCurvesRatedValuesValidationRules _generatePlotPumpCurvesRatedValuesValidationRules = new GeneratePlotPumpCurvesRatedValuesValidationRules();

    public RatedValuesViewModelValidator()
    {
        RuleFor(viewModel => viewModel.DataSource).SetValidator(_generatePlotPumpCurvesRatedValuesValidationRules);

        Custom(viewModel =>
                   {
                       if (viewModel.DataSource == null)
                           return null;

                       ValidationResult validationResult = _generatePlotPumpCurvesRatedValuesValidationRules.Validate(viewModel.DataSource, viewModel.DataSource.GetPropertyName(vm => vm.Head));

                       return !validationResult.IsValid ? new ValidationFailure(viewModel.GetPropertyName(vm => vm.Head), CombineErrors(validationResult.Errors)) : null;
                   } );
    }

    private static string CombineErrors(IEnumerable<ValidationFailure> errors)
    {
        StringBuilder combinedErrors = new StringBuilder();

        errors.ForEach(error => combinedErrors.AppendLine(error.ErrorMessage));

        return combinedErrors.ToString();
    }
}

ビューモデルの検証クラスでは、プロパティ「ヘッド」に定義された検証ルールを再利用し、それらをビューモデル プロパティ「ヘッド」のルールとして公開します。ご覧のとおり、私が頻繁に行うことになるコードには、非常に多くのコードがあります。流暢な検証フレームワーク機能を使用して、この「検証プロパティ プロジェクション」を設定できますか?

4

1 に答える 1

0

フレームワークでこれを行う方法は見つかりませんでしたが、ワンライナーとしてやりたいことを実行できるようにする拡張メソッドを作成しました。

例:

class PumpCurveViewModelValidationRules : AbstractValidator<PumpCurveViewModel>
{
    readonly ConstantPumpCurveParametersValidationRules _constantParametersValidator = new ConstantPumpCurveParametersValidationRules();

    public PumpCurveViewModelValidationRules()
    {
        this.AddPropertyProjectionRule<PumpCurveViewModelValidationRules, PumpCurveViewModel, ConstantPumpParameters>(c => c.Speed, vm => vm.CurveSpeed, vm => vm.DataSource.ConstantPumpParameters, _constantParametersValidator);          
    }
}
于 2010-07-29T10:58:00.833 に答える