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

标签 c# system.reactive

从事件创建可观察对象时,以下是最常见的方法:

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);
}

因为有“事件名称”-重载:

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

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

有没有办法优化这段代码?或者事情就是这样?

最佳答案

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

然后,添加和删除处理程序并同时维护类型安全的唯一真正可行的方法是使用您在问题中首先显示的语法。

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!"));

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

关于c# - Observable.FromEventPattern(addHandler,removeHandler)-简化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27390347/

相关文章:

c# - 将多选下拉列表附加到数组

c# - 在 Intranet 应用程序中实现安全性

c# - 哪个最适合数据存储结构/类?

c# - 套接字问题和 OutOfMemory 错误

c# - 业务对象属性 : model as Objects or Enums?

c# - 使用Reactive Extensions模拟UIElement的点击

c# - 为什么 Observable.ToEnumerable() 在底层序列完成之前不会产生值?

c# - 如何使用 Rx 定期执行代码直到第一次成功执行?

system.reactive - 如何在另一个可观察对象发出 true 时缓冲项目,并在 false 时释放它们

multithreading - Observable 对不同线程上的队列更改没有反应