这个让我彻夜难眠。假设我有一个像这样的简单界面:
public interface INotifier
{
IObservable<string> Messages { get; }
void SendMessage(string message);
}
如果不在内部使用Subject<string>
或等效的有状态构造,我如何实现此接口?
我并不是说这是一场教条式的辩论,更像是一场思想实验。如果这是一个真正的问题,我会毫不犹豫地使用一个主题来做这件事。我只是好奇,是否有人有一种我没有考虑过的方法,他们可以分享,也许可以拓宽我们的集体视野。
查看ISubject<T>
的定义(稍微简化):
interface ISubject<T> : IObserver<T>, IObservable<T>
{
void OnValue(T value);
void OnError(Exception error);
void OnCompleted();
IDisposable Subscribe(IObserver<T> observer);
}
现在来看一个概念上等价的INotifier
:定义
interface INotifier : IObservable<string>
{
IDisposable Subscribe(IObserver<string> observer);
void OnValue(string value);
}
你看到问题了吗?你的INotifier
准确地描述了一个主题的概念,减去OnError
和OnCompleted
。虽然这并不明显,但你的问题可以归结为:"没有主题,我怎么能实现一个主题?"
在某个时刻,订阅者观察到的每一个通知都必须来自某个地方。如果最终的来源是"冷",那么你不应该在任何地方都需要受试者。如果最终来源是"热"的,这意味着这些值是从程序外部推送给你的,但不是作为IObservable<T>
,那么你必须使用主题。这是不可避免的。在这些情况下,目标是将主题直接置于最终来源。
我同意@Timothy Shields的观点。您正在尝试在不使用主题的情况下实现ISubject
。我也理解您简化了界面以保持问题的重点(对此表示感谢)。然而,在这种情况下,我认为需要退后一步,查看系统的分层/设计,以理解为什么您有一个似乎是事件代理的类。大多数时候,当我看到一个主题被使用时,它要么是有效的(1%的时间),要么实际上是系统的结构方式,这是需要解决的问题。