実行中のメソッドをログ(C#)

実行時にメソッド名やコールスタックなどのメタデータを取得する仕組みをreflectionと言うそうですが、C#だと、System.Reflectionクラスがその機能を提供してくれます。下記は実行中のメソッドを表示するサンプルプログラム。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Hoge();
            while (true) { ;}
        }

        static void Hoge()
        {
            // これを必要な箇所にコピペしまくっても良いけど…
            MethodBase mb = MethodInfo.GetCurrentMethod();
            Debug.WriteLine("[Debug]" + mb.DeclaringType.Name + 
                                  "." + mb.Name + "を実行中");
            // こっちのほうが綺麗で便利。
            Logger.Log();
        }
    }

    class Logger
    {
        public static void Log()
        {
            StackTrace st = new StackTrace(true);
            StackFrame sf1 = st.GetFrame(1);
            MethodBase mb1 = sf1.GetMethod();
            StackFrame sf2 = st.GetFrame(2);
            MethodBase mb2 = sf2.GetMethod();
            Debug.WriteLine("[Log]" 
              + Path.GetFileName(sf2.GetFileName()) + ":" 
              + sf2.GetFileLineNumber() + "行目 "
              + mb2.DeclaringType.Name + "." + mb2.Name + "から呼ばれた");
            Debug.WriteLine("[Log]"
              + Path.GetFileName(sf1.GetFileName()) + ":"
              + sf1.GetFileLineNumber() + "行目 "
              + mb1.DeclaringType.Name + "." + mb1.Name + "を実行中");

            // ※ デバッグ情報が無く、行番号を取得できないなら
            // string address = sf2.GetMethod().ToString() 
            //      + "@ IL_" + sf2.GetILOffset().ToString("X4");
            // Debug.WriteLine(address);
        }
    }
}

ファイル名と行番号の取得は、デバッグ情報の無いリリースビルドに対しては無効なので、その場合は、上記のGetILOffsetを用いて、MSIL(.NETの中間言語)でのオフセットアドレスを取得し、MSIL逆アセンブラ(Ildasm.exe)に実行ファイルをドロップして、表示されたアドレスの1行前を見る。Ildasm.exeは、Program Files\Microsoft SDKs\Windows\v7.0A\Bin とかにあるはず。