2

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 fieldInfo = source.GetType().GetField(eventName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.GetField); 理由はわかりませんが、fieldInfo が常に残っているため、アクセスしようとするとnull例外が発生します。eventDelegate残念ながら、この場合 ClickEvent が見つからない理由を見つけることができません。メンバーeventNameには、KinectControl クラスのイベントの名前である値「Click」があります。また、このサイトで回答を検索しましたが (ただし、これまでのところ解決策はありませんでした)、DotNetPearls.com などのあらゆる種類のブログを読みましたが、それでもここで間違いを見つけることができないようです。あなたが私を助けてくれることを願っています。前もって感謝します!

編集:追加BindingFlags.Static; FieldInfo でそれを忘れていました。ありがとう@Michael Gunter。それでもうまくいきません。

4

2 に答える 2

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 });
于 2013-06-04T16:10:27.020 に答える
0

呼び出すだけの方が良いでしょうUIElement.RaiseEvent- RoutedEvents は実際の EventHandler 実装を持つ必要はありません - そのため、単にその作業をUIElement.AddHandlerandに委譲しUIElement.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));
    }
}

お役に立てれば!

于 2013-06-04T17:16:55.337 に答える