これで、すべてのフィールドに検証機能を追加することができます。
public class InvoiceLineItem
{
public readonly Field<Guid> ItemID = new Field<Guid>();
public readonly Field<Guid> InvoiceID = new Field<Guid>();
public readonly Field<int> LineNumber = new Field<int>();
public readonly Field<decimal> Quantity =
new Field<decimal>(new RangeValidator(1, 100));
public readonly Field<bool> Taxable = new Field<bool>();
public readonly Field<decimal> UnitPrice =
new Field<decimal>(new RangeValidator(0.01M, 9999M));
public readonly Field<decimal> Weight =
new Field<decimal>(new RangeValidator(0.1M, 99M));
public readonly Field<decimal> ExtendedPrice =
new Field<decimal>();
}
指定した範囲外の値を代入しようとすると、自動的にArgument Exception(引数例外)を返すようになりました。次に、Valueの変更に対してクラスオブジェクトが自動で反応するようにします。ここでも、Fieldクラスを拡張することでこの機能を実装します。
public class Field<DATA_TYPE>
{
public class ValueChangedEventArgs : EventArgs
{
internal ValueChangedEventArgs(DATA_TYPE oldValue,
DATA_TYPE newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
public readonly DATA_TYPE OldValue;
public readonly DATA_TYPE NewValue;
}
public event EventHandler<ValueChangedEventArgs> ValueChanged;
private void Fire_ValueChanged(DATA_TYPE oldValue,
DATA_TYPE newValue)
{
if (ValueChanged != null)
ValueChanged(this,
new ValueChangedEventArgs(oldValue, newValue));
}
public DATA_TYPE Value
{
get { return m_Value; }
set
{
if (!Equals(m_Value, value))
{
DATA_TYPE oldValue = m_Value;
m_Validator.Validate(value);
m_Value = value;
Fire_ValueChanged(oldValue, m_Value);
}
}
}
}
この機能は、クラスに「ビジネスロジック」を含めるようになった段階で使用することができます。
public class Field<DATA_TYPE>
{
public class ValueChangedEventArgs : EventArgs
{
internal ValueChangedEventArgs(DATA_TYPE oldValue,
DATA_TYPE newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
public readonly DATA_TYPE OldValue;
public readonly DATA_TYPE NewValue;
}
public event EventHandler<ValueChangedEventArgs> ValueChanged;
private void Fire_ValueChanged(DATA_TYPE oldValue,
DATA_TYPE newValue)
{
if (ValueChanged != null)
ValueChanged(this,
new ValueChangedEventArgs(oldValue, newValue));
}
public DATA_TYPE Value
{
get { return m_Value; }
set
{
if (!Equals(m_Value, value))
{
DATA_TYPE oldValue = m_Value;
m_Validator.Validate(value);
m_Value = value;
Fire_ValueChanged(oldValue, m_Value);
}
}
}
}
まとめ
ここまでで、検証機能とイベント駆動ロジックの両方を実装する簡単なアーキテクチャができました。これはほんの始まりに過ぎません。次回は、クラスレベルに同様の原則を適用して、インテリジェントなエンティティやコレクションを生成します。今後の記事では、ユーザーインターフェース(UI)に対するデータのバインドやインテリジェントな永続性についても取り上げる予定です。
詳細情報
本連載における情報は、Dynamic Concepts Development社発行のガイド『Smart Architecture』に基づいています。これはオープンなアーキテクチャであるとともに、開発者コミュニティで自由に利用できる推奨インターフェース群です。商企業は、このアーキテクチャを利用して実装やツールセットの開発を行うことができます。
