引用的块文本几乎解释了为什么您不应该使用Subject<T>
,但更简单地说,您正在结合观察者和可观察者的功能,同时在两者之间注入某种状态(无论您是封装还是扩展)。
这就是你遇到麻烦的地方;这些责任应该彼此分开和区别开来。
也就是说,在您的具体情况下,我建议您将您的担忧分解为更小的部分。
首先,您的线程很热,并且始终监视硬件以获取发出通知的信号。你通常会怎么做? 事件。所以让我们从那个开始。
让我们定义EventArgs
您的事件将触发。
// The event args that has the information.
public class BaseFrameEventArgs : EventArgs
{
public BaseFrameEventArgs(IBaseFrame baseFrame)
{
// Validate parameters.
if (baseFrame == null) throw new ArgumentNullException("IBaseFrame");
// Set values.
BaseFrame = baseFrame;
}
// Poor man's immutability.
public IBaseFrame BaseFrame { get; private set; }
}
现在,将触发事件的类。请注意,这可能是一个静态类(因为您总是有一个线程在运行监视硬件缓冲区),或者您按需调用的订阅该. 您必须根据需要进行修改。
public class BaseFrameMonitor
{
// You want to make this access thread safe
public event EventHandler<BaseFrameEventArgs> HardwareEvent;
public BaseFrameMonitor()
{
// Create/subscribe to your thread that
// drains hardware signals.
}
}
所以现在你有一个公开事件的类。Observables 可以很好地处理事件。如此之多,以至于IObservable<T>
如果您遵循标准事件模式,通过 class 上的静态FromEventPattern
方法将事件流(将事件流视为事件的多次触发)转换为实现的Observable
一流支持。
使用您的事件源和FromEventPattern
方法,我们可以轻松地创建一个IObservable<EventPattern<BaseFrameEventArgs>>
(EventPattern<TEventArgs>
该类体现了您在 .NET 事件中看到的内容,特别是派生自的实例EventArgs
和表示发送者的对象),如下所示:
// The event source.
// Or you might not need this if your class is static and exposes
// the event as a static event.
var source = new BaseFrameMonitor();
// Create the observable. It's going to be hot
// as the events are hot.
IObservable<EventPattern<BaseFrameEventArgs>> observable = Observable.
FromEventPattern<BaseFrameEventArgs>(
h => source.HardwareEvent += h,
h => source.HardwareEvent -= h);
当然,你想要一个IObservable<IBaseFrame>
, 但这很简单,使用类上的Select
扩展方法Observable
来创建一个投影(就像你在 LINQ 中一样,我们可以将所有这些包装在一个易于使用的方法中):
public IObservable<IBaseFrame> CreateHardwareObservable()
{
// The event source.
// Or you might not need this if your class is static and exposes
// the event as a static event.
var source = new BaseFrameMonitor();
// Create the observable. It's going to be hot
// as the events are hot.
IObservable<EventPattern<BaseFrameEventArgs>> observable = Observable.
FromEventPattern<BaseFrameEventArgs>(
h => source.HardwareEvent += h,
h => source.HardwareEvent -= h);
// Return the observable, but projected.
return observable.Select(i => i.EventArgs.BaseFrame);
}