2013-06-04 35 views
2

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

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并调用适当的方法是“Menu_Point” -object从KinectControl-类继承的控制。

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

它调用下面的方法:

识别点击的手势, “源” 分别为 “Menu_Point” -object提出了这样的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 }); 
      } 
     } 
    } 

它工作正常intil Raise方法被调用并得到这一行: FieldInfo fieldInfo = source.GetType().GetField(eventName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField); 我不知道为什么,但fieldInfo ist始终保持null这将导致异常如果eventDelegate试图访问它。不幸的是,我无法找到在这种情况下找不到ClickEvent的原因。成员eventName的值为“Click”,它是KinectControl类中Event的名称。我还在这个网站上搜索了答案(但迄今为止,没有任何解决方案对我有帮助),并且我阅读了各种关于DotNetPearls.com这样的博客,但是我仍然无法在这里找到这个错误。 我希望你能帮助我。提前致谢!

编辑:加入BindingFlags.Static;在FieldInfo中忘记了。谢谢@Michael Gunter。尽管如此,仍然不起作用。

+0

这里的AddHandler()方法很可能是DependencyObject.AddHandler()方法。它将事件存储在名为“dependencyPropertyValues”的字段中的内部字典中。你必须用反思去挖掘它。这*不是*应该很容易。 –

+0

确实听起来不容易。幸运的是,@Andreas Prechtl的解决方案为我工作。该方法遍历(我认为)所有框架元素的所有事件并最终找到“Click”事件。 – Crash

回答

0

这将是更好,如果你只是调用UIElement.RaiseEvent - RoutedEvents不需要有一个实际的事件处理程序的实现 - 这就是为什么他们只是委派工作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)); 
    } 
} 

希望这有助于!

+0

非常感谢,它立即工作:) – Crash

+0

很高兴我可以帮助:) –

0

这似乎工作:

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 }); 
+1

不幸的是没有工作。不知何故,eventField像fieldInfo一样保持“null”。虽然谢谢! – Crash