とはデータを持たない、標識としてのアノテーション。結構使う機会が多い。
例えば、GUIではなくGUIとデータバインドしているDTOの変更管理をしたい場合。通常は全てのプロパティの変更をチェックしてダーティ(変更が発生したか)を検査するのだが、検査の対象となるプロパティを明示したいとしよう。
このような場合、CheckDirtyAttributeクラスを書き、マーカアノテーションを対象のプロパティに記述するのが手っ取り早い。
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public class CheckDirtyAttribute : Attribute
{}
:
:
[CheckDirty]
public string Hoge
{
get { return this.hoge; }
set
{
//AOP等で自動で実行する場合、変更の検出コードは不要
if ( !this.hoge.Equals(value) )
{
this.NotifyPropertyChanged("Hoge");
this.hoge= value;
}
}}
あとは、対象の型からCheckDirtyAttributeが記述されているプロパティだけをPropertyInfoの配列に抽出するコードを用意しておいて、
PropertyInfo[] propInfos = Array.FindAll( this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy), delegate(PropertyInfo info) { return info.IsDefined(typeof(CheckDirtyAttribute), true); });
.NETの場合、データバインドクライアント(この場合はDTO)のプロパティの変更通知に関してはINotifyPropertyChangedインタフェースを実装することで実現しているが、その中でCheckDirtyAttributeを検査することで確実に対象のプロパティのみをダーティの検出に用いる訳だ。
protected bool isDirty = false;
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String propertyName)
{
//対象のプロパティの場合、監視状態をスイッチ
if (propertyNameがpropInfos配列に含まれるか)
{
this.isDirty = true; //ダーティ!
}
if (PropertyChanged != null)
{
PropertyChanged(this
, new PropertyChangedEventArgs(propertyName));
}
}
実用には、適当なタイミングで変更状態をリセットする(isDirtyをクリアする)メソッドが必要だろう。
問題は「何を持ってダーティとするか」の判定。例ではEqualsメソッドを唯一の判定に使用しているが、この判定をカスタマイズしたい場合はアノテーションだけではどうにもならないんで、はてどうしたものか。
追記:
囚人さんにコメント頂いたたが全くその通りで、DTOのプロパティのアクセサを自ら書く場合、わざわざ上のように遠回りなことは必要ない。囚人さんが書いてくれた通り単純にプロパティ変更時にダーティとすれば良い。
public string Hoge
{
get { return this.hoge; }
set
{
if ( !this.hoge.Equals(value) )
{
this.isDirty = true; //ダーティ!
this.NotifyPropertyChanged(”Hoge”);
this.hoge= value;
}
}
}
私の場合は以前に書いたようにINotifyPropertyChangedインタフェースの実装をAOPで自動で行うケースでは、アクセサにコードを追加しないのが前提だったので今回のようにアノテーションによる変更監視の必要性があった訳だ。紛らわしくて申し訳ない。