2017-04-12 8 views
0
public class AwaitableRoutedEvent 
{ 
    private TaskCompletionSource<object> _tcs; 

    public async Task When<TypeOfControl>(TypeOfControl source, string nameOfEvent) 
    { 
     _tcs = new TaskCompletionSource<object>(); 

     var targetEventInfo = source.GetType().GetEvent(nameOfEvent); 
     Delegate tempEventHandler = 
      Delegate.CreateDelegate(
       targetEventInfo.EventHandlerType, 
       GetType().GetMethod(nameof(RoutedEventHandler), BindingFlags.Instance | BindingFlags.Public)); 

     try 
     { 
      targetEventInfo.AddEventHandler(source, tempEventHandler); 

      await _tcs.Task; 
     } 
     finally 
     { 
      targetEventInfo.RemoveEventHandler(source, tempEventHandler); 
      _tcs = null; 
     } 
    } 

    public void RoutedEventHandler(object sender, RoutedEventArgs arguments) 
    { 
     _tcs.TrySetResult(null); 
    } 
} 

上記のcalssは 'awaitable' RoutedEventHandlerイベントを表します。目標はawait new AwaitableRoutedEvent().When(button_object, "click");のように使用することです。対象メソッドにバインドできません... from Delegate.Create(..)+ Reflection

IF MAKE public void RoutedEventHandler(object sender, RoutedEventArgs arguments) STATIC ...と変更するとBindingsFlags ...動作します。しかし私は静的が好きではありません。非静的バージョンでは例外がスローされます:Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type

私は何かを見逃しましたか?

+0

問題の解決策を見つけた場合は、質問の編集ではなく回答として投稿する必要があります。 – Servy

+0

私が間違っている場合は私を修正しますが、 'async/await'はステートマシンを静的インスタンスにコンパイルします。私はそれが 'static'メソッドを使う必要があると思います。多分、C#7の最新バージョンでは動作が異なりますが、それについてはわかりません。あなたのコードを逆アセンブルしようとしましたか? – VMAtm

+0

@VMAtmいいえ、あなたは間違っています。私はちょうどDelega.Create(...)のいくつかの他の過負荷を使用し、それは大丈夫だった。私はMSILを掘り下げませんでした。なぜなら、近い将来、その問題を発見したいと思います。 –

答えて

0

RoutedEventHandlerはインスタンスメソッドであるため、デリゲートを作成するとき、あなたはメソッドが呼び出されるオブジェクトのインスタンスを提供する必要があります。

Delegate tempEventHandler = 
     Delegate.CreateDelegate(
      targetEventInfo.EventHandlerType, 
      this, 
      GetType().GetMethod(nameof(RoutedEventHandler), BindingFlags.Instance | BindingFlags.Public)); 

をそして、あなたが書くことがあるので、一見、あなたは、すべてのことを必要としません

RoutedEventHandler tempEventHandler = this.MyRoutedEventhander; 

public void MyRoutedEventHandler(object sender, RoutedEventArgs arguments) 
{ 
    _tcs.TrySetResult(null); 
} 
関連する問題