PIABで属性を使ってインターセプト対象メソッドを指定する

はじめに

以前書いた 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 Wankuma : MarshalByRefObject
{
    // 作成した属性を付与
    [EventLogCallHandler]
    public void Cry()
    {
        Console.WriteLine("クマ〜");
    }
}

作成した EventLogCallHandlerAttribute をCry メソッドに付与しています。構成ファイルでメソッドを指定する必要はありません。
これで PolicyInjection.Create メソッドで生成した Wankuma インスタンスの、 Cry メソッドが呼び出される前と後にイベントログが出力されます。

まとめ

インターセプトするメソッドの指定は、構成ファイルを記述するよりも、属性を使った方が遥かに楽ですね。ちなみに、PIAB には既にロギングや検証など数種類の CallHandler と HandlerAttribute が用意されています。今回のサンプルで取り上げたロギングは、自作せずに用意されているクラスを使うのも良いでしょう。