はじめに
以前書いた Policy Injection Application Block のサンプルは
構成ファイルでインターセプトするメソッドを指定していました。
インターセプトするメソッドは属性でも指定可能なので、
今回はその方法を試してみました。
カスタム CallHandler を作成
[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class EventLogCallHandler : ICallHandler
{
public int Order { get; set; }
public EventLogCallHandler(NameValueCollection attributes)
{
// このコンストラクタは必須みたい
}
private const string SOURCE = "PIABSample";
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
// メソッド呼び出し前にログを出力
EventLog.WriteEntry(SOURCE,
string.Format("{0} メソッドを呼び出します。", input.MethodBase.Name),
EventLogEntryType.Information);
// メソッド呼び出し
IMethodReturn result = getNext()(input, getNext);
// メソッド呼び出し後にログを出力
if (result.Exception != null)
{
// 例外が発生したとき
EventLog.WriteEntry(SOURCE,
string.Format("{0} メソッド呼び出しで例外が発生しました。", input.MethodBase.Name),
EventLogEntryType.Error);
}
else
{
EventLog.WriteEntry(SOURCE,
string.Format("{0} メソッドを呼び出しました。", input.MethodBase.Name),
EventLogEntryType.Information);
}
return result;
}
}
前に作成したものをそのまま流用。
カスタム HandlerAttribute を作成
public class EventLogCallHandlerAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler()
{
return new EventLogCallHandler();
}
}
EventLogCallHandler クラスのインスタンスを生成して返しているだけ。
インターセプト対象のメソッドを持つクラスを作成
public class Wankuma : MarshalByRefObject
{
// 作成した属性を付与
[EventLogCallHandler]
public void Cry()
{
Console.WriteLine("クマ~");
}
}
作成した EventLogCallHandlerAttribute をCry メソッドに付与しています。
構成ファイルでメソッドを指定する必要はありません。
これで PolicyInjection.Create メソッドで生成した Wankuma インスタンスの、
Cry メソッドが呼び出される前と後にイベントログが出力されます。
まとめ
インターセプトするメソッドの指定は、構成ファイルを記述するよりも、
属性を使った方が遥かに楽ですね。
ちなみに、PIAB には既にロギングや検証など数種類の CallHandler と HandlerAttribute が用意されています。
今回のサンプルで取り上げたロギングは、自作せずに用意されているクラスを使うのも良いでしょう。