我已经开始使用官方初学者指南来尝试 .NET 的反应式扩展,但很多方法重载对我不起作用(我已经参考了 System.Reactive)。我不确定这是因为如何指导已经过时还是有其他原因(如果我缺少一些程序集,请告诉我)。以下是原始和更改的代码:
using System;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Forms;
namespace RxFormsSandbox
{
class Program
{
static void Main(string[] arguments)
{
var textBox = new TextBox();
var form = new Form { Controls = { textBox } };
// MY CODE (WORKING)
var mouseMoves = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
handlerAction => (_, args) => handlerAction(args),
handler => form.MouseMove += handler,
handler => form.MouseMove -= handler);
var input = Observable.FromEvent<EventHandler, EventArgs>(
handlerAction => (_, args) => handlerAction(args),
handler => textBox.TextChanged += handler,
handler => textBox.TextChanged -= handler);
var mouseMovesSubscription = mouseMoves.Select(x => x.Location.ToString()).Subscribe(Console.WriteLine);
var inputSubscription = input.Subscribe(x => Console.WriteLine(textBox.Text)); // can I do this without directly accessing 'label' (via sender)
// END OF MY CODE
// ORIGINAL CODE AS PROVIDED IN THE SAMPLE
// var mouseMoves = Observable.FromEvent<MouseEventArgs>(form, "MouseMove");
// var input = Observable.FromEvent<MouseEventArgs>(textBox, "TextChanged");
//
// var mouseMovesSubscription = mouseMoves.Select(x => x.EventArgs.Location.ToString()).Subscribe(Console.WriteLine);
// var inputSubscription = input.Subscribe(x => Console.WriteLine(((TextBox)x.Sender).Text));
// END OF ORIGINAL SAMPLE CODE
using (new CompositeDisposable(mouseMovesSubscription, inputSubscription))
{
Application.Run(form);
}
}
}
}
前提是该方法的签名确实在版本之间发生了变化,有几件事让我对我的解决方案感到困扰,我想问是否有更好的方法:
- 我重写的版本要长得多,我认为表现力较差。有没有办法让它更短(理想情况下不引入魔术弦)?
- 输入。订阅(x => Console.WriteLine(textBox.Text));不是很好,因为它引用了外部代码。我想以某种方式通过"发件人"属性访问它。
我的程序集来自 NuGet,其版本为 1.0.10621.0。
如果你想模仿旧的方式,你可以使用 FromEventPattern
方法:
var mouseMoves = Observable.FromEventPattern<MouseEventArgs>(form, "MouseMove");
这样做的唯一缺点是会丢失使用 FromEvent 方法时获得的类型安全性。(FromEventPattern
还有一个使用委托的重载,但它处理EventHandler<T>
但MouseMove
是 .Net 2.0 之前的重载)
至于你的第二点,为什么"引用外部代码"是一件坏事?闭包是 C# 语言的重要组成部分,实际上没有理由避免它们。事实上,在事件订阅代码的代码中,您也在这样做(捕获表单):
var mouseMoves = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
handlerAction => (_, args) => handlerAction(args),
handler => form.MouseMove += handler,
handler => form.MouseMove -= handler);