[C#]どのイベントが発生しているかを見てみる。

コントロールのイベントがどの様に発生しているか(発生順番)を調べたいなーって思って、いろいろ試したけど、うまくいかない。

単純にイベントに対して処理の追加は次のようにかける。

button1.Click += (s,e) => MessageBox.Show("Click");

このイベントへの処理の追加を自動でできないものか考えてみた。結果としてはうまくいかず。。。

以下試した方法。

リフレクションの機能を使う

クラスの型情報(Type)に対してGetEvents()ですべてのイベントを取得し、そのハンドラに対して処理を追加することができる。

            var t = target.GetType();

            var evs = t.GetEvents();

            foreach (var ev in evs)
            {
                Trace.WriteLine("ev=" + ev.Name);

                var evnt = t.GetEvent(ev.Name);

                Action<object, EventArgs> addHandlerDelegaete = (s, e) =>
                    {
                        Trace.WriteLine(s.ToString() + "," + e.ToString());
                    };

                Delegate d = Delegate.CreateDelegate(evnt.EventHandlerType, addHandlerDelegaete.GetMethodInfo());

                evnt.AddEventHandler(target, d);
            }

やりたいことは、発生したイベントの名前を表示すること。上記の処理をフォームに貼りつけたButtonコントロールに施し実行すると以下のようなログが出てくる。

System.Windows.Forms.Button, Text: button1,System.Windows.Forms.UICuesEventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.InvalidateEventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.InvalidateEventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.InvalidateEventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.PaintEventArgs
System.Windows.Forms.Button, Text: button1,System.EventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.InvalidateEventArgs
System.Windows.Forms.Button, Text: button1,System.Windows.Forms.PaintEventArgs

単純に画面に表示された時点だけでかなりのイベントが発生。だけど、肝心なイベント名が出ません。本当はaddHandlerDelegaeteを次のようにしたかった。

            foreach (var ev in evs)
            {
                Trace.WriteLine("ev=" + ev.Name);

                var evnt = t.GetEvent(ev.Name);

                Action<object, EventArgs> addHandlerDelegaete = (s, e) =>
                    {
                        Trace.WriteLine("eventName:" + ev.Name);
                    };

                Delegate d = Delegate.CreateDelegate(evnt.EventHandlerType, addHandlerDelegaete.GetMethodInfo());

                evnt.AddEventHandler(target, d);
            }

結果、実行時、Delegate.CreateDelegate()で例外発生。スコープ外の変数を参照したのだけれど、どうもこの方法がダメらしい。要はスコープ外の変数の参照は不可。次の例外が発生。

追加情報: ターゲット メソッドとデリゲート型との間に、シグネチャまたはセキュリティ透過性の互換性がないため、ターゲット メソッドにバインドできません。

ちーん