2010-12-02 8 views
2

タイトルのため申し訳ありませんが、明示的ではありません。リフレクトでフィールドを参照する方法

Further to my precedent question私は動的に(リフレクションによって)取得されたイベントオブジェクトにメソッドをサブスクライブします。問題のオブジェクトは、コントロールのフィールドです。

public void SubscribeEvents(Control control) 
{ 
    Type controlType = control.GetType(); 
    FieldInfo[] fields = controlType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 

    MethodInfo method = typeof(Trace).GetMethod("WriteTrace"); 

    // "button1" hardcoded for the sample 
    FieldInfo f = controlType.GetField("button1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 

    // "Click" hardcoded for the sample 
    EventInfo eInfo = f.FieldType.GetEvent("Click"); 

    if (eInfo != null) 
    { 
     EventHandler dummyDelegate = (s, e) => WriteTrace(s, e, eInfo.Name); 
     Delegate realDelegate = Delegate.CreateDelegate(eInfo.EventHandlerType, dummyDelegate.Target, dummyDelegate.Method); 
     eInfo.AddEventHandler(?????, realDelegate); // How can I reference the variable button1 ??? 
    } 
} 

変数 'button1'の参照方法はわかりません。私はこのようなものを試してみた:

public void SubscribeEvents(Control control) 
{ 
    Type controlType = control.GetType(); 
    FieldInfo[] fields = controlType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 

    MethodInfo method = typeof(Trace).GetMethod("WriteTrace"); 

    // "button1" hardcoded for the sample 
    FieldInfo f = controlType.GetField("button1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 

    // "Click" hardcoded for the sample 
    EventInfo eInfo = f.FieldType.GetEvent("Click"); 

    Type t = f.FieldType; 
    object o = Activator.CreateInstance(t); 

    f.GetValue(o); 

    if (eInfo != null) 
    { 
     EventHandler dummyDelegate = (s, e) => WriteTrace(s, e, eInfo.Name); 
     Delegate realDelegate = Delegate.CreateDelegate(eInfo.EventHandlerType, dummyDelegate.Target, dummyDelegate.Method); 
     eInfo.AddEventHandler(o, realDelegate); // Why can I refer to the variable button1 ??? 
    } 
} 

しかし、私はここに例外があります。

 f.GetValue(o); 

System.ArgumentExceptionのをしたタイプに定義されたフィールド「ボタン1」が「WindowsFormsApplication1.Form1」は=未処理 メッセージ'System.Windows.Forms.Button'型の対象オブジェクト上のフィールドではありません。

答えて

5

これは、Buttonという新しいインスタンスを作成して、明らかに存在しないbutton1プロパティの値を取得しようとしているからです。

これを置き換えます。私が持っている

public static T GetFieldValue<T>(object obj, string fieldName) 
{ 
    if (obj == null) 
     throw new ArgumentNullException("obj"); 

    var field = obj.GetType().GetField(fieldName, BindingFlags.Public | 
                BindingFlags.NonPublic | 
                BindingFlags.Instance); 

    if (field == null) 
     throw new ArgumentException("fieldName", "No such field was found."); 

    if (!typeof(T).IsAssignableFrom(field.FieldType)) 
     throw new InvalidOperationException("Field type and requested type are not compatible."); 

    return (T)field.GetValue(obj); 
} 
+0

:あなたは任意のオブジェクトのフィールドの値を取得するために、このようなメソッドを使用することができます

object o = f.GetValue(control); 

:これで

Type t = f.FieldType; object o = Activator.CreateInstance(t); f.GetValue(o); 

問題:button1(と他のボタン)でうまく動作しますが、カスタムフィールドのときはnullを返します。 オブジェクトo = f。 GetValue(コントロール); // fがMyClass型のフィールドのフィールド情報である場合、o = null fは良い値を返します。 – Florian

+0

@Florian: "カスタムフィールド"とは何ですか? – cdhowie

+0

@cdhowie: プライベートMyClass _myClass; //「カスタム」フィールド(悪い変換? private System.Windows.Forms.Button button1; – Florian