【问题标题】:How to reference a field by reflection如何通过反射引用字段
【发布时间】:2010-12-02 14:28:29
【问题描述】:

对不起,标题不明确。

Further to my precedent question,我想订阅一个动态检索的事件对象的方法(通过反射)。有问题的对象是 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 未处理 在“WindowsFormsApplication1.Form1”类型上定义的 Message=Field 'button1' 不是“System.Windows.Forms.Button”类型的目标对象上的字段。

【问题讨论】:

    标签: .net reflection c#-2.0 fieldinfo


    【解决方案1】:

    这是因为您正在尝试创建 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);
    }
    

    【讨论】:

    • 我有一个问题:它适用于 button1(和其他按钮)但当它是一个自定义字段时它返回 null : object o = f.GetValue(control); // 如果 f 是来自 MyClass 类型的字段的字段信息,则 o = null 而 f 具有良好的值
    • @Florian:“自定义字段”到底是什么?
    • @cdhowie : private MyClass _myClass; // “自定义”字段(翻译错误?private System.Windows.Forms.Button button1;
    • 那么您将需要使用从typeof(MyClass) 类型获得的FieldInfo 对象。 FieldInfo 一种类型的对象不能用于不相关的类型,即使它们共享字段名称。请参阅我发布的方法——您可以使用它来获取任何对象上的任意字段。例如:Button button = GetFieldValue&lt;Button&gt;("button1", _myClass);
    • 好的,我去测试一下!非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2013-10-24
    相关资源
    最近更新 更多