如何使用 Rx 和 F# 将 WPF Button.Click 事件转换为 Observable
我正在尝试复制一些从 Button.Click
事件创建 IObservable
的 C# 代码。 我想将此代码移植到 F#。
这是编译时没有错误的原始 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
作为 RoatedEventHandler
构造函数的参数。
另一方面,C# 编译器似乎没有问题接受 h =>; new RoutedEventHandler(h)
有趣的是,在两个代码示例(C# 和 F#)中,h
的类型都是 EventHandler
。
我从 F# 编译器收到的错误消息是:
错误 2 该表达式的类型应为 obj -> RoutedEventArgs -> 路由事件参数单位但这里有类型 EventHandler
我在PresentationCore 中找到的 RoutedEventHandler 的签名是:
public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
正如你所看到的,它确实需要object
和 RoulatedEventArgs
作为参数,因此 F# 编译器实际上是正确的。
C# 编译器是否在幕后执行了一些 F# 编译器无法执行的操作,或者我只是在这里遗漏了一些东西?
不管怎样,我怎样才能在 F# 中实现这个功能呢?
I am trying to replicate some C# code which creates an IObservable
from a Button.Click
event.
I want to port this code to F#.
Here is the original C# code which compiles without errors:
Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
h => new RoutedEventHandler(h),
h => btn.Click += h,
h => btn.Click -= h))
Here is my failing attempt to do the same in 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))
Everything is happy except for the second line of the statement.
The F# compiler complains about fun h -> RoutedEventHandler(h)
because
it doesn't want to except h
as a parameter to the RoutedEventHandler
constructor.
On th other hand the C# compiler seems to have no problem accepting h => new RoutedEventHandler(h)
Interestingly enough, in both code samples (C# and F#) the type of h
is EventHandler<RoutedEventArgs>
.
The error message I am getting from the F# compiler is:
Error 2 This expression was expected to have type obj -> RoutedEventArgs -> unit but here has type EventHandler
The signature for RoutedEventHandler
that I found inside PresentationCore is:
public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
As you can see it does take an object
and RoutedEventArgs
as parameters, so the F# compiler is actually correct.
Is there some magic that the C# compiler does behind the scenes to make this work that the F# compiler doesn't or am I just missing something here?
Either way, how can I make this work in F#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我所知,从 WPF Button.Click 事件中创建 IObservable<_> 的最简单方法是对其进行强制转换:
检查 obsClick...
这是可能的,因为标准 .NET 事件的 F# 表示形式是类型(在本例中)
IEvent
。从文档中可以看出,IEvent 实现了 IObservable。换句话说,在 F# 中,每个事件都已经是一个 IObservable。The easiest way I know of to make an
IObservable<_>
out of a WPF Button.Click event is to cast it:Examining obsClick...
This is possible because the F# representation of standard .NET events is the type (in this case)
IEvent<Windows.RoutedEventHandler,Windows.RoutedEventArgs>
. As you can see from the documentation, IEvent implements IObservable. In other words, in F# every single event already is anIObservable
.Joel Mueller 说得很对,所以仅供记录:C# 代码的直接翻译将是
Joel Mueller is spot on, so just for the record: a direct translation of the C# code would be