繁体   English   中英

通过c#中的反射提升事件

[英]Raise an event via reflection in c#

我想编写一个可重用的函数来通过反射来引发事件。

搜索之后,我发现了类似的问题: 如何通过.NET / C#中的反射来引发事件?

它一直有效,直到我向WinForm控件注册一个事件处理程序并尝试调用它。 私有字段' <EventName> '只是消失了。

下面是我的简化代码,它可以重现问题:

Program.cs中:

public static void Main()
{
    Control control = new Control();
    control.Click += new EventHandler(control_Click);

    MethodInfo eventInvoker = ReflectionHelper.GetEventInvoker(control, "Click");
    eventInvoker.Invoke(control, new object[] {null, null});
}

static void control_Click(object sender, EventArgs e)
{
    Console.WriteLine("Clicked !!!!!!!!!!!");
}

这是我的ReflectionHelper类:

public static class ReflectionHelper
{
    /// <summary>
    /// Gets method that will be invoked the event is raised.
    /// </summary>
    /// <param name="obj">Object that contains the event.</param>
    /// <param name="eventName">Event Name.</param>
    /// <returns></returns>
    public static MethodInfo GetEventInvoker(object obj, string eventName)
    {
        // --- Begin parameters checking code -----------------------------
        Debug.Assert(obj != null);
        Debug.Assert(!string.IsNullOrEmpty(eventName));
        // --- End parameters checking code -------------------------------

        // prepare current processing type
        Type currentType = obj.GetType();

        // try to get special event decleration
        while (true)
        {
            FieldInfo fieldInfo = currentType.GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField);

            if (fieldInfo == null)
            {
                if (currentType.BaseType != null)
                {
                    // move deeper
                    currentType = currentType.BaseType;
                    continue;
                }

                Debug.Fail(string.Format("Not found event named {0} in object type {1}", eventName, obj));
                return null;
            }

            // found
            return ((MulticastDelegate)fieldInfo.GetValue(obj)).Method;
        }
    }

附加信息:

  • 同班的活动:工作。
  • 不同类中的事件,同一汇编中的子类:工作。
  • 不同的汇编,调试和发布模式中的事件:工作。
  • WinForm,DevExpress中的事件......:没有用

任何帮助表示赞赏。

WinForms中的事件通常被覆盖,并且没有一对一的委托支持。 相反,类(基本上)具有事件 - >委托映射的字典,并且仅在添加事件时创建委托。 因此,一旦您使用反射访问该字段,您就无法假设有一个代表支持该事件。

编辑:这会成为同样问题的牺牲品,但比将其作为一个字段并将其投射更好。

  var eventInfo = currentType.GetEvent(eventName); 
  var eventRaiseMethod = eventInfo.GetRaiseMethod()
  eventRaiseMethod.Invoke()

这是我的一些代码。 'obj'是您要调用方法的对象,'methodName'是您要调用的方法:

public void Invoke(Object obj, String methodName) {
    MethodInfo m = obj.GetType().GetMethod(methodName);

    if (m != null) {
        m.Invoke(obj, null);
    }
}

用法示例:

String s = " test string ";
Invoke(s, "Trim");

我还没有在程序集中对它进行测试,但我从中获取的项目已经过测试,效果很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM