先ほど書いたValidation Application Blockの記事で、えムナウさんから型付データセットのRewardPoints(System.Int32)に文字列を入れたら入力値検証前に落ちるのではないか?とのご指摘を受けました。
Validation Application Block を使おう!! ~構成ファイル編~
確かに、おっしゃる通りです。
そこで対応策。
RewardPoints の System.Int32 を System.String 型にしてしまい、カスタムValidatorを作って対応します。カスタムValidatorでは、Stringをintに変換し、変換したintに対して検証をかけるという感じです。実装例は以下の通りです。
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration;
using System.Collections.Specialized;
namespace ValidationABSample.CustomValidator
{
[ConfigurationElementType(typeof(CustomValidatorData))]
public class IntRangeValidator : Validator
{
private int _lowerBound = 0;
private RangeBoundaryType _lowerBoundType = RangeBoundaryType.Ignore;
private int _upperBound = 0;
private RangeBoundaryType _upperBoundType = RangeBoundaryType.Ignore;
// コンストラクタ
public IntRangeValidator(NameValueCollection attributes)
: base(null, null)
{
_lowerBound = Int32.Parse(attributes.Get("lowerBound"));
_upperBound = Int32.Parse(attributes.Get("upperBound"));
if (attributes.Get("lowerBoundType").Equals("Exclusive"))
{
_lowerBoundType = RangeBoundaryType.Exclusive;
}
if (attributes.Get("lowerBoundType").Equals("Inclusive"))
{
_lowerBoundType = RangeBoundaryType.Inclusive;
}
if (attributes.Get("upperBoundType").Equals("Exclusive"))
{
_upperBoundType = RangeBoundaryType.Exclusive;
}
if (attributes.Get("upperBoundType").Equals("Inclusive"))
{
_upperBoundType = RangeBoundaryType.Inclusive;
}
}
// デフォルトメッセージ
protected override string DefaultMessageTemplate
{
get { return "数値範囲チェック。The value must fall within the range {0} ({1}) - {2} ({3})."; }
}
// 検証メソッド
protected override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
{
if (objectToValidate != null)
{
try
{
int valueToValidate = int.Parse(objectToValidate.ToString());
RangeValidator<int> validator = new RangeValidator<int>(_lowerBound, _lowerBoundType, _upperBound, _upperBoundType);
ValidationResults results = validator.Validate(valueToValidate);
if (!results.IsValid)
{
string message = string.Format(DefaultMessageTemplate, _lowerBound, _lowerBoundType, _upperBound, _upperBoundType);
this.LogValidationResult(validationResults, message, currentTarget, key);
}
}
catch (FormatException)
{
string message = "数値を入力してください。";
this.LogValidationResult(validationResults, message, currentTarget, key);
}
}
}
}
}
このカスタムValidatorを使って検証することで、文字列でなかったら「数値を入力してください。」というメッセージを、数値で範囲チェック違反があったら、設定したデフォルトメッセージを表示するようにできます。
EnterpriseLibraryのValidatorを継承することで、こんなようにカスタムValidatorを自由に作る事もできます。
こんな感じでどうでしょうか?
実行結果
