2017-04-12 151 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); 
    } 
} 

上面的代碼表示'awaitable'RoutedEventHandler事件。目標是使用它像await new AwaitableRoutedEvent().When(button_object, "click");無法綁定到目標方法,因爲...從Delegate.Create(..)+ Reflection

如果我製作public void RoutedEventHandler(object sender, RoutedEventArgs arguments)靜態 ...和更改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

糾正我,如果我錯了,但'異步/等待'編譯它的狀態機爲靜態實例。我認爲這就是爲什麼它需要你使用'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); 
} 
相關問題