4

タイトルで申し訳ありませんが、それは明示的ではありません。

前の質問に加えて、(リフレクションを介して) 動的に取得されたイベント オブジェクトにメソッドをサブスクライブしたいと考えています。問題のオブジェクトは Control のフィールドです:

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 は処理されませんでした Message=Field タイプ 'WindowsFormsApplication1.Form1' で定義された 'button1' は、タイプ 'System.Windows.Forms.Button' のターゲット オブジェクトのフィールドではありません。

4

1 に答える 1

7

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

これを置き換えます:

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

f.GetValue(o);

これとともに:

object o = f.GetValue(control);

次のようなメソッドを使用して、任意のオブジェクトのフィールドの値を取得できます。

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);
}
于 2010-12-02T14:33:59.823 に答える