簡體   English   中英

通過反射C#查找事件

[英]finding events via reflection c#

我有一個關於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並調用適當方法的Control是從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 ist始終保持為null ,如果eventDelegate試圖獲取對它的訪問權限,則會導致異常。 不幸的是,在這種情況下,我無法找到未找到ClickEvent的原因。 成員eventName的值“ Click”是KinectControl類中Event的名稱。 我也在該站點上搜索了答案(但是到目前為止,沒有一種解決方案對我有幫助),並且我閱讀了各種有關DotNetPearls.com之類的博客,但我似乎仍然找不到這里的錯誤。 我希望你能幫助我。 提前致謝!

編輯:添加BindingFlags.Static ; 在FieldInfo中忘記了。 謝謝@邁克爾·甘特。 不過仍然無法正常工作。

這似乎可行:

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

如果只調用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));
    }
}

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM