- PR -

event delegateに登録されているメソッドの一覧の取得

1
投稿者投稿内容
cranpun
会議室デビュー日: 2006/01/22
投稿数: 2
投稿日時: 2006-01-22 16:03
お世話になります.

コントロールのもつevent delegateに登録されているメソッドの情報を取得する方法はないのでしょうか?

例えば,C#の場合,
Button button1 = new Button();
button1.Click += new System.EventHandler(form1.button1_Click);
という記述があるさいに,
button1というインスタンスから,
event delegateに登録されているメソッド名とそのメソッドを取得したいのです.
この場合,
Form1のbutton1_Clickというメソッドが,
Clickに関連づけられているということを知るには,
どのようにすればよいのでしょうか?

よろしくお願いします.
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-01-22 18:24
Button を例に挙げます。

Button のイベントは、私たちがイベントを実装するように単純にはなっていません。
私たちがイベントを実装するときは、
public event EventHander Click;
という風に、Click フィールドを用意しますが、Button(Controlから継承しているクラス)はそうなっていません。
パフォーマンスの関係から、いちいちそんなフィールドを持っていないのです(メモリの無駄)。
Button は多くのイベントを持っていますが、その殆どにイベントハンドラは登録されませんよね?ほとんど Click を使うだけの時が多いと思います。

なので Control から継承しているクラスのイベントは EventHandlerList 型のフィールド(.NET2 の場合 events という名前だった)一つだけになっています。

button1.Click += new System.EventHandler(form1.button1_Click);
が実行されたとき初めて、events に Click 用の EventHandler 型のインスタンスが登録されます。
button1.Click += new System.EventHandler(form1.button2_Click);
と続けて実行されたときは、events から Click 用の EventHander を探してきて、そこにデリゲートチェインします。EventHander デリゲート自体もリンクリストになっていますからね。

まずは、button1 から events フィールドを取り出し、そこから、Click 用の EventHandler を取得してください。

単純なイベントの実装方法の場合でも、コンパイラが自動で生成する仕組みを知ってなければなりません。
public event EventHander Click;
と書いたら、private な EventHander デリゲート型のフィールド(名前のルールが決まっているのかどうか分りません)が生成されます。
それをリフレクションで取り出す必要があります。

無事 Click の EventHandler のフィールドが取得できたら、そこからさらにリフレクションを使って、リンクリストを辿るという方法もありますが、GetInvocationList() を呼び出して Delegate の一覧を取得するのが単純かな。

結論。リフレクションを使うにしても、名前が分らないので、難しいと思います。

_________________
囚人のジレンマな日々
cranpun
会議室デビュー日: 2006/01/22
投稿数: 2
投稿日時: 2006-01-22 19:17
早速の返信ありがとうございます.

引用:

囚人さんの書き込み (2006-01-22 18:24) より:
Button を例に挙げます。

Button のイベントは、私たちがイベントを実装するように単純にはなっていません。
私たちがイベントを実装するときは、
public event EventHander Click;
という風に、Click フィールドを用意しますが、Button(Controlから継承しているクラス)はそうなっていません。
パフォーマンスの関係から、いちいちそんなフィールドを持っていないのです(メモリの無駄)。
Button は多くのイベントを持っていますが、その殆どにイベントハンドラは登録されませんよね?ほとんど Click を使うだけの時が多いと思います。

なので Control から継承しているクラスのイベントは EventHandlerList 型のフィールド(.NET2 の場合 events という名前だった)一つだけになっています。

button1.Click += new System.EventHandler(form1.button1_Click);
が実行されたとき初めて、events に Click 用の EventHandler 型のインスタンスが登録されます。
button1.Click += new System.EventHandler(form1.button2_Click);
と続けて実行されたときは、events から Click 用の EventHander を探してきて、そこにデリゲートチェインします。EventHander デリゲート自体もリンクリストになっていますからね。

まずは、button1 から events フィールドを取り出し、そこから、Click 用の EventHandler を取得してください。

単純なイベントの実装方法の場合でも、コンパイラが自動で生成する仕組みを知ってなければなりません。
public event EventHander Click;
と書いたら、private な EventHander デリゲート型のフィールド(名前のルールが決まっているのかどうか分りません)が生成されます。
それをリフレクションで取り出す必要があります。

無事 Click の EventHandler のフィールドが取得できたら、そこからさらにリフレクションを使って、リンクリストを辿るという方法もありますが、GetInvocationList() を呼び出して Delegate の一覧を取得するのが単純かな。

結論。リフレクションを使うにしても、名前が分らないので、難しいと思います。





その後,さらに調査していたところ,以下のページを見つけました.
http://www.technewsgroups.net/group/microsoft.public.dotnet.general/topic4196.aspx
このページのとおり,実行してみたところ,無事登録されているイベントハンドラのリストを取得できました.
囚人さまのコメントにあるとおり,リフレクションを使用して取得できるようです.

一応,目的は実現できましたが,このコードがなにをしているのか,
理解が不完全でした.
しかし,囚人さまのコメントを参考にもう一度眺めたところ,
やっと理解できました.ありがとうございます.

囚人さまのコメントを参考にもう一度コードを見てみると,このページにあるGetEventIDField()というメソッドが,EventHandlerを探している部分のようだということがわかりました.
このページによると,EventHandlerは,Event[イベント名]という命名規則があるようです.

ただ,すこし実験してわかったことが,
BackColorChangedなどの*Changedというイベントだけは例外だということです.
*Changedというイベントに対応するEventHandlerの名前は,
EventBackColorのように,Changedがない名前となっていました.

まだ,数個のイベントについてしか確認していないので,確実とはいえないですが,
一応,この方法でなんとかなりそうです.

囚人さま,ありがとうございました.
1

スキルアップ/キャリアアップ(JOB@IT)