Observable.FromEventPattern(addHandler,removeHandler) - 简化?

时间:2014-12-09 22:47:43

标签: c# system.reactive

从事件创建observable时,看起来以下是最常见的方式:

var o = Observable.FromEventPattern(h => source.Event += h,
                                    h => source.Event -= h);

在某些情况下,我觉得这种形式有点单调乏味,我希望以同样的方式处理多个事件。但这看起来并不容易,因为事件本身似乎无法参数化,如非编译代码所示:

private IObservable MakeAnObservableFromThisEvent(Event event)
{
    return Observable.FromEventPattern(h => event += h,
                                        h => event -= h);

}

private void MakeAlotOfObservables(object source)
{
    MakeAnObservableFromThisEvent(source.OneEvent);
    MakeAnObservableFromThisEvent(source.AnotherEvent);
    MakeAnObservableFromThisEvent(source.ThirdEvent);

    //or even
    MakeAnObservableFromThisEvent(() => source.ThirdEvent);
}

原因是有'事件名称' -overload:

var o = Observable.FromEventPattern< >(source, "Event");

但是这个东西有或多或少的魔法字符串......

有没有优化此代码?或者这只是事情的方式?

2 个答案:

答案 0 :(得分:2)

问题是事件处理程序具有“值类型”语义(如字符串),因此将它们作为参数传递仅在您打算调用它们时才有用。有效地添加新处理程序会创建一个新的委托实例,并且不会修改原始文件。

然后,只有真正可行的方法来添加和删除处理程序并同时保持类型安全,这与您在问题中首先显示的语法有关。

var o =
    Observable
        .FromEventPattern(
            h => source.Event += h,
            h => source.Event -= h);

然而,还有另一种选择,我已经使用了很多 - 而且那是使用扩展方法。

如果我有这门课程:

public class Foo
{
    public event EventHandler<EventArgs> Click;
}

我可以写一个扩展方法:

public static class FooEx
{
    public static IObservable<EventPattern<EventArgs>> Clicks(this Foo source)
    {
        return
            Observable
                .FromEventPattern<EventArgs>(
                    h => source.Click += h,
                    h => source.Click -= h);
    }
}

那允许我写这个:

var foo = new Foo();
foo.Clicks().Subscribe(x => Console.WriteLine("Click!"));

您可以为每个类型和事件有效地编写一次扩展方法,然后可以在需要的地方使用它,并使用大大改进的语法。

答案 1 :(得分:2)

它不是一个直接的解决方案,但ReactiveUI-Events基本上实现了@Enigmativity对整个框架的建议。所以你可以这样做:

Observable.Merge(
    Foo.Events().Clicked.Select(_ => Unit.Default),
    Foo.Events().KeyUp.Select(_ => Unit.Default));