我試圖複製一些從Button.Click
事件創建IObservable
的C#代碼。 我想將此代碼移植到F#。如何使用Rx和F將WPF Button.Click事件轉換爲Observable#
這裏是原來的C#代碼編譯沒有錯誤:
Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),
h => btn.Click += h,
h => btn.Click -= h))
這是我沒有嘗試做相同的F#:
Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
Func<EventHandler<RoutedEventArgs>, RoutedEventHandler>(fun h -> RoutedEventHandler(h)),
Action<RoutedEventHandler>(fun h -> btn.Click.AddHandler h),
Action<RoutedEventHandler>(fun h -> btn.Click.RemoveHandler h))
一切,除了第二行快樂該聲明。
F#編譯器會抱怨,因爲fun h -> RoutedEventHandler(h)
它 並不想除了h
作爲參數的構造函數RoutedEventHandler
。
在th另一方面C#編譯器似乎也沒有問題接受h => new RoutedEventHandler(h)
有趣的是,這兩個代碼的樣品(C#和F#)的h
類型是EventHandler<RoutedEventArgs>
英寸
我從F#編譯器得到的錯誤信息是:
錯誤2,預計這種表達有型的obj - > RoutedEventArgs - >單元,但這裏有EventHandler類型
的爲RoutedEventHandler
,我發現裏面PresentationCore簽名是:
public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
正如你所看到的,它確實需要object
和RoutedEventArgs
作爲參數,所以F#編譯器實際上是正確的。
C#編譯器在幕後做了些什麼以使F#編譯器不工作或我只是在這裏丟失什麼?
無論哪種方式,我如何使這項工作在F#?
謝謝,看着反射的C#代碼讓我意識到,「H」實際上得到擴大到'h。Invoke',然後將其視爲代表'(s,e)=> h.Invoke(s,e)'的方法組,從而滿足RoutedEventHandler簽名。一旦明確,很明顯,你用你建議的F#實現就是正確的。 我也同意,Joel Mueller建議的較爲詳細的轉換是首選,除非您需要直接獲取發件人的持有者(例如,不通過args.Source),因爲它只返回RoutedEventArgs的IObservable。 – 2011-02-27 17:31:02