2013-06-04 37 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