[英]How to implement an event using Reactive Extensions
The Reactive Extensions allow you to easily subscribe to an event using Observable.FromEventPattern
, but I can't find anything on how you might implement an event when you have an IObservable
. Reactive Extensions允许您使用
Observable.FromEventPattern
轻松订阅事件,但是当您拥有IObservable
时,我无法找到有关如何实现事件的任何信息。
My situation is this: I need to implement an interface which contains an event. 我的情况是这样的:我需要实现一个包含事件的接口。 That event is supposed to be called whenever a certain value of my object changes, and for thread safety reasons I need to call this event on a certain
SynchronizationContext
. 每当我的对象的某个值发生变化时,就会调用该事件,出于线程安全的原因,我需要在某个
SynchronizationContext
上调用此事件。 I am also supposed to call each event handler with the current value on registration. 我也应该在注册时使用当前值调用每个事件处理程序。
public interface IFooWatcher
{
event FooChangedHandler FooChanged;
}
Getting an observable that does what I want is rather easy with Rx using BehaviorSubject
: 使用
BehaviorSubject
使用Rx获得一个可以完成我想要的观察是相当容易的:
public class FooWatcher
{
private readonly BehaviorSubject<Foo> m_subject;
private readonly IObservable<Foo> m_observable;
public FooWatcher(SynchronizationContext synchronizationContext, Foo initialValue)
{
m_subject = new BehaviorSubject<Foo>(initialValue);
m_observable = m_subject
.DistinctUntilChanged()
.ObserveOn(synchronizationContext);
}
public event FooChangedHandler FooChanged
{
add { /* ??? */ }
remove { /* ??? */ }
}
}
Now I am looking for an easy way to have the add
and remove
functions subscribe and unsubscribe the passed FooChangedHandler
as an Observer<Foo>
on m_observable
. 现在我正在寻找一种简单的方法有
add
和remove
功能,订阅和取消订阅传递FooChangedHandler
作为Observer<Foo>
上m_observable
。 My current implementation looks similar to this: 我目前的实现看起来类似于:
add
{
lock (m_lock)
{
IDisposable disp = m_observable.Subscribe(value);
m_registeredObservers.Add(
new KeyValuePair<FooChangedHandler, IDisposable>(
value, disp));
}
}
remove
{
lock (m_lock)
{
KeyValuePair<FooChangedHandler, IDisposable> observerDisposable =
m_registeredObservers
.First(pair => object.Equals(pair.Key, value));
m_registeredObservers.Remove(observerDisposable);
observerDisposable.Value.Dispose();
}
}
However, I hope to find an easier solution, because I need to implement several of these events (of differing handler types). 但是,我希望找到一个更简单的解决方案,因为我需要实现其中几个事件(不同的处理程序类型)。 I tried to roll my own generic solution but it creates some additional problems that need to be worked around (in particular, how you generically work with a delegate that takes a parameter of
T
), so I would prefer to find an existing solution that bridges the gap in this direction - just as FromEventPattern
does the reverse. 我试图推出自己的通用解决方案,但它会产生一些需要解决的其他问题(特别是,你如何通常使用带有
T
参数的委托),所以我宁愿找到一个现有的解决方案来桥接这方面的差距 - 就像FromEventPattern
反过来一样。
You could do this: 你可以这样做:
public event FooChangedHandler FooChanged
{
add { m_observable.ToEvent().OnNext += value; }
remove { m_observable.ToEvent().OnNext -= value; }
}
However, on the remove, I think perhaps you just may want to dispose of the subscription ... or perhaps get the Action from ToEvent() and store that as a member. 但是,在删除时,我想也许您可能只想处理订阅...或者从ToEvent()获取Action并将其存储为成员。 Untested.
未经测试。
EDIT: You'll have to use Action instead of a FooChangedHandler delegate, however. 编辑:但是,您必须使用Action而不是FooChangedHandler委托。
EDIT 2: Here's a tested version. 编辑2:这是一个经过测试的版本。 I suppose you need to use FooChangedHandler, however, since you have a bunch of these pre-existing handlers?
我想你需要使用FooChangedHandler,因为你有一堆这些预先存在的处理程序?
void Main()
{
IObservable<Foo> foos = new [] { new Foo { X = 1 }, new Foo { X = 2 } }.ToObservable();
var watcher = new FooWatcher(SynchronizationContext.Current, new Foo { X = 12 });
watcher.FooChanged += o => o.X.Dump();
foos.Subscribe(watcher.Subject.OnNext);
}
// Define other methods and classes here
//public delegate void FooChangedHandler(Foo foo);
public interface IFooWatcher
{
event Action<Foo> FooChanged;
}
public class Foo {
public int X { get; set; }
}
public class FooWatcher
{
private readonly BehaviorSubject<Foo> m_subject;
public BehaviorSubject<Foo> Subject { get { return m_subject; } }
private readonly IObservable<Foo> m_observable;
public FooWatcher(SynchronizationContext synchronizationContext, Foo initialValue)
{
m_subject = new BehaviorSubject<Foo>(initialValue);
m_observable = m_subject
.DistinctUntilChanged();
}
public event Action<Foo> FooChanged
{
add { m_observable.ToEvent().OnNext += value; }
remove { m_observable.ToEvent().OnNext -= value; }
}
}
Given that you are already mixing the boundaries between reactive and more normal code, you could do a less reactive version. 鉴于您已经在混合反应和更正常的代码之间的界限,您可以做一个反应较少的版本。 To start simply declare a normal event pattern
开始只是声明一个正常的事件模式
public event FooChangedHandler FooChanged;
protected void OnFooChanged(Foo)
{
var temp = FooChanged;
if (temp != null)
{
temp(new FooChangedEventArgs(Foo));
}
}
and then simply connect the observable to it in the constructor 然后只需在构造函数中将observable连接到它
m_Observable.Subscribe(foo => OnFooChanged(foo));
It's not very Rx but it is incredibly simple. 它不是非常Rx但它非常简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.