- 検証ロジックをモデル クラス自体に追加します。
- POCO をロジックで爆破し、ActiveRecord パターンを使用することになるため、最適なアプローチではありません。
- Operation オブジェクトをラップする検証ロジックのデコレータ クラスを作成します。
-既存のラッパーをラップする必要があるという違いがあり、抽象化のレベルを吹き飛ばすことになるという違いがあるため、これも推奨されないより良いアプローチだと思います。
- 操作を検証したいときに渡すサービス クラスを作成します。
-おそらく、そのようなことを達成するのはあなたの場合ではありません(Webサービスまたは別のタイプのリモートサービスについて言っていることを正しく理解している場合)。たとえば、これらの検証ルールに制限がある場合、このソリューションはより適しています複数のクライアント向けに集中化されており、具体的なアプリケーションに厳密ではありません。
私は次の解決策を支持します:
以下を含むバリデータ プロジェクトをソリューションに追加します。
アプリケーションが .xml ファイルから読み取る外部スキーマに対してパラメーターを検証するロジック。
プロジェクトで使用する各 POCO オブジェクトの検証ルールであり、検証が必要です (または、これらのルールをより高いレベルで適用することもできます。つまり、POCO ではなく、POCO のいくつかのラッパーを既に実装している場合、ただし、ベスト プラクティスは、規則を POCO に直接適用することです – よりクリーンで正しいアプローチ)
だから:
1- POCO には、プロパティと単純な検証 SelfValidate() が含まれます。
namespace Core.Domain {
public class Operation : ValidatableDomainObject {
#region Properties
public virtual String Name { get; set; }
public virtual ISet Phases { get; set; }
#endregion Properties
#region Validation
public override ValidationResult SelfValidate() {
return ValidationHelper.Validate(this);
}
#endregion Validation
}
}
2- POCO Validator には、XML ファイルに基づいて POCO の検証に適用する必要があるルールが含まれます。
#region Usings
using System.Linq;
using FluentValidation;
using FluentValidation.Results;
#endregion Usings
namespace Core.Validation {
public class OperationValidator : AbstractValidator {
#region .Ctors
///
/// .Ctor used for operation purpose
///
public OperationValidator() {
Validate();
}
#endregion .Ctors
///
/// Validation rules for Operation
///
private void Validate() {
//here you may get validations rules from you xml file and structure the following code after your requirements
//Name
RuleFor(x => x.Name).Length(2, 20).WithMessage("Operation name should have length between 2 and 20 symbols");
//ApplicationFormsWrapper
Custom(entity => {
foreach (var item in entity.Phases)
if (item.PhaseState == null)
return new ValidationFailure("Phases", "First Phase is missing");
return null;
});
}
}
}
3- ValidatableDomainObject クラスを追加し、System.ComponentModel.IDataErrorInfo を実装します (ユーザー インターフェイスがバインドできるカスタム エラー情報を提供する機能を提供します)。
#region Usings
using System.ComponentModel;
using System.Linq;
using FluentValidation.Results;
using Core.Validation.Helpers;
#endregion Usings
namespace Core.Domain.Base {
public abstract class ValidatableDomainObject : DomainObject, IDataErrorInfo {
public abstract ValidationResult SelfValidate();
public bool IsValid {
get { return SelfValidate().IsValid; }
}
public string Error {
get { return ValidationHelper.GetError(SelfValidate()); }
}
public string this[string columnName] {
get {
var validationResults = SelfValidate();
if (validationResults == null) return string.Empty;
var columnResults = validationResults.Errors.FirstOrDefault(x => string.Compare(x.PropertyName, columnName, true) == 0);
return columnResults != null ? columnResults.ErrorMessage : string.Empty;
}
}
}
}
4-次の ValidationHelper を追加します。
#region Usings
using System;
using System.Text;
using FluentValidation;
using FluentValidation.Results;
#endregion Usings
namespace Core.Validation.Helpers {
public class ValidationHelper {
public static ValidationResult Validate(TK entity)
where T : IValidator, new()
where TK : class {
IValidator validator = new T();
return validator.Validate(entity);
}
public static string GetError(ValidationResult result) {
var validationErrors = new StringBuilder();
foreach (var validationFailure in result.Errors) {
validationErrors.Append(validationFailure.ErrorMessage);
validationErrors.Append(Environment.NewLine);
}
return validationErrors.ToString();
}
}
}
アプリケーションコードで次のことを実行できます。
- サービスまたはビューモデル レベルで、検証エラーを取得するためにこれを行うことができます。
var operation = new Operation(){Name="A"};
var validationResults = operation.SelfValidate();
- ビュー レベルでは、次のように記述できます (この場合、検証エラーが表示された場合、それらは OperationValidator クラスから直接取得されます)。
<TextBox Text="{Binding CurrentOperation.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
注: 実装は FluentValidation (流暢なインターフェイスとラムダ式を使用する .NET 用の小さな検証ライブラリ) に基づいています。http://fluentvalidation.codeplex.com/を参照してください。ドメイン オブジェクトから検証を分離するメカニズムを説明します。