从事件创建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");
但是这个东西有或多或少的魔法字符串......
有没有优化此代码?或者这只是事情的方式?
答案 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));