反应性扩展缺少方法重载

时间:2012-07-06 17:31:35

标签: c# system.reactive

我已经开始使用官方beginner's guide来使用.NET的Reactive Extensions,但很多方法重载对我来说都不起作用(我引用了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);
            }
        }
    }
}

在前提下,方法的签名确实在发行版之间发生了变化,有一些事情让我对我的解决方案感到不满,我想问一下是否有更好的方法:

  1. 我的重写版本明显更长,我认为不那么富有表现力。有没有办法让它更短(理想情况下不引入魔术弦)?
  2. input.Subscribe(x =&gt; Console.WriteLine(textBox.Text));不是很好,因为它引用了外部代码。我想以某种方式通过'sender'属性访问它。
  3. 我的程序集来自NuGet,其版本为1.0.10621.0。

1 个答案:

答案 0 :(得分:3)

如果您想模仿旧方法,可以使用FromEventPattern方法:

var mouseMoves = Observable.FromEventPattern<MouseEventArgs>(form, "MouseMove"); 

这样做的唯一缺点是,您在使用FromEvent方法时会失去类型安全性。 (FromEventPattern也有一个使用委托的重载,但它处理EventHandler<T>,但MouseMove是.Net 2.0之前的<)>

至于你的第二点,为什么“引用外部代码”是一件坏事? Closures是C#语言的重要组成部分,并且没有理由避免它们。实际上,在事件订阅代码中的代码中,您也正在执行它(捕获表单):

var mouseMoves = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
               handlerAction => (_, args) => handlerAction(args),
               handler => form.MouseMove += handler,
               handler => form.MouseMove -= handler);