通过反射c#查找事件



我有一个关于c#中的事件和反射的问题。我目前正在使用微软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 fieldInfo = source.GetType().GetField(eventName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField);我不知道为什么,但是fieldInfo列表总是保留null,如果eventDelegate试图访问它会导致异常。不幸的是,我无法找到在这种情况下找不到ClickEvent的原因。成员eventName的值为"Click",这是kinectcontrol类中事件的名称。我也在这个网站上搜索了答案(但到目前为止没有一个解决方案对我有帮助),我读了各种关于DotNetPearls.com的博客,但我似乎仍然找不到这里的错误。我希望你能帮助我。提前感谢!

编辑:add BindingFlags.Static;我在田野里忘记了。谢谢@Michael Gunter。

如果你只调用UIElement.RaiseEvent会更好- RoutedEvents不需要有一个实际的EventHandler实现-这就是为什么他们简单地将工作委托给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));
    }
}

希望这对你有帮助!

这似乎可以工作:

var eventField = source.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
var eventDelegate = eventField.GetValue(source) as MulticastDelegate;
if (eventDelegate != null)
    eventDelegate.DynamicInvoke(new object[] { source, eventArgs });

相关内容

  • 没有找到相关文章

最新更新