c# - 通过反射查找事件 C#

标签 c# events reflection fieldinfo

我有一个关于 C# 中的事件和反射的问题。 我目前正在使用 Microsoft Kinect (SDK 1.7) 进行编程,并希望实现与“一键按下”方法不同的点击。 ClickEvent 本身在 KinectControl 类中声明。

    public partial class KinectControl : UserControl
    {
        /**
        \brief Default Click event 
        */

        public static readonly RoutedEvent ClickEvent =
            EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(KinectControl)); 
        [...]

        public event RoutedEventHandler Click
        {
            add
            {
                AddHandler(ClickEvent, value);
            }
            remove
            {
                RemoveHandler(ClickEvent, value);
            }
        }
    } 

应该引发此 ClickEvent 并调用适当方法的控件是一个继承自 KinectControl 类的“Menu_Point”对象。

识别点击手势后,“源”和“Menu_Point”对象引发 ClickEvent,如下所示:

invokeCtrl.Raise<RoutedEventArgs>("Click", new RoutedEventArgs(KinectControl.ClickEvent));

调用以下方法:

        public static void Raise<TEventArgs>(this object source, string eventName, TEventArgs eventArgs) where TEventArgs : EventArgs
    {
        var list = 
            source.GetType().GetFields(BindingFlags.Public | 
            BindingFlags.NonPublic | BindingFlags.Instance | 
            BindingFlags.Static | BindingFlags.SetField | 
            BindingFlags.InvokeMethod | BindingFlags.Instance);
        FieldInfo fieldInfo = 
            source.GetType().GetField(eventName, BindingFlags.Public | 
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static |
            BindingFlags.GetField);

        var eventDelegate = 
            (MulticastDelegate)fieldInfo.GetValue(source);

        if (eventDelegate != null)
        {
            foreach (var handler in eventDelegate.GetInvocationList())
            {
                handler.Method.Invoke(handler.Target, new object[]{ source, eventArgs });
            }
        }
    }

在调用 Raise 方法并到达此行之前,它工作正常: FieldInfo 字段信息 = source.GetType().GetField(eventName, BindingFlags.Public | 绑定(bind)标志.NonPublic | BindingFlags.实例 | BindingFlags.静态 | BindingFlags.GetField); 我不知道为什么,但 fieldInfo 总是保持 null,如果 eventDelegate 试图访问它,这会导致异常。不幸的是,我找不到在这种情况下找不到 ClickEvent 的原因。成员 eventName 的值为“Click”,它是 KinectControl 类中事件的名称。我还在这个网站上搜索了答案(但到目前为止,没有一个解决方案对我有帮助),我阅读了各种关于博客的文章,比如 DotNetPearls.com,但我似乎仍然找不到这里的错误。 我希望你能帮助我。提前致谢!

编辑:添加了BindingFlags.Static;在 FieldInfo 中忘记了。谢谢@Michael Gunter。不过还是不行。

最佳答案

如果您只调用 UIElement.RaiseEvent 会更好 - RoutedEvents 不需要有实际的 EventHandler 实现 - 这就是为什么他们只是将工作委托(delegate)给 UIElement.AddHandlerUIElement.RemoveHandler

话虽如此 - 以下是您最有可能找到该事件的方式:

    public static RoutedEvent GetEvent(this UIElement source, string eventName)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        if (string.IsNullOrEmpty(eventName))
            throw new ArgumentException("eventName");

        // check if the type is directly in there, otherwise you need a second pass and a more general approach
        RoutedEvent routedEvent = null;

        // this may return null...
        RoutedEvent[] events = EventManager.GetRoutedEventsForOwner(source.GetType());

        if (events != null)
            routedEvent = events.FirstOrDefault(p => p.Name == eventName);

        return routedEvent ?? EventManager.GetRoutedEvents().FirstOrDefault(p => p.OwnerType.IsInstanceOfType(source) && p.Name == eventName);
    }

    public static void RaiseEvent(this UIElement source, string eventName)
    {
        RoutedEvent routedEvent = GetEvent(source, eventName);

        if (routedEvent != null)
            source.RaiseEvent(new RoutedEventArgs(routedEvent, source));
    }
}

希望这对您有所帮助!

关于c# - 通过反射查找事件 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16921780/

相关文章:

c# - 为什么 Assembly.GetTypes() 不会返回封闭泛型类型?

c# - 将方法作为参数传递

C# - 遍历和调用类成员

c# - C# 中是否有 Guava Striped-Class 的等效项?

C# 在添加的线程中触发事件

javascript - SSE失败:使用事件推送插件在grails中注册事件监听器后出现问题

java - 如何使用java获取类和方法中的所有变量和类型数据

c# - 索引一小部分值的正确方法

c# - 无法将 MvvMCross 6.x iOS 颜色绑定(bind)到 MvxColor WithConversion

c# - UserControl 的事件处理程序未触发