c#中的IObserver和IObservable,用于观察者vs委托,事件
本文关键字:观察者 vs 委托 事件 用于 IObserver IObservable 中的 | 更新日期: 2023-09-27 18:17:46
我要做的就是实现观察者模式。
所以,我想出了这个解决方案:
我们有一个PoliceHeadQuarters,它的主要工作是向所有订阅它的人发送通知。考虑DSP、Inspector和SubInspector类都订阅了PoliceHeadQuarters。
使用事件和委托我写了
public class HeadQuarters
{
public delegate void NewDelegate(object sender, EventArgs e);
public event EventHandler NewEvent;
public void RaiseANotification()
{
var handler = this.NewEvent;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
public class SubInspector
{
public void Listen(object sender, EventArgs e)
{
MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString()));
}
}
public class Inspector
{
public void Listen(object sender, EventArgs e)
{
MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString()));
}
}
我是这样调用它的
var headQuarters = new HeadQuarters();
var SubInspector = new SubInspector();
var Inspector = new Inspector();
headQuarters.NewEvent += Inspector.Listen;
headQuarters.NewEvent += SubInspector.Listen;
headQuarters.RaiseANotification();
因此,无论何时调用函数RaiseANotification(), Inspector和SubInspector类都会收到通知。
DotNet Framework 4,4.5似乎支持一种叫做IObserver和IObservable的新方式。
谁能给我一个超级简单的例子使用IObservable和IObserver模式的上述场景?我在谷歌上搜索了一下,却发现互联网上可用的例子过于臃肿,难以理解。
我的想法:(可能我认为这是错误的)
class DSP : IObserver //since it observes the headquarters ?
class PoliceHeadQuarters: IObservable // since here's where we send the notifications ?
提前感谢。
编辑:有人还说MSDN文档对于IObservable @也是不正确的IObservable vs Plain Events还是我为什么要用IObservable
这是一个修改的MSDN的例子,以适应您的框架:
public struct Message
{
string text;
public Message(string newText)
{
this.text = newText;
}
public string Text
{
get
{
return this.text;
}
}
}
public class Headquarters : IObservable<Message>
{
public Headquarters()
{
observers = new List<IObserver<Message>>();
}
private List<IObserver<Message>> observers;
public IDisposable Subscribe(IObserver<Message> observer)
{
if (!observers.Contains(observer))
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
private class Unsubscriber : IDisposable
{
private List<IObserver<Message>> _observers;
private IObserver<Message> _observer;
public Unsubscriber(List<IObserver<Message>> observers, IObserver<Message> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
}
}
public void SendMessage(Nullable<Message> loc)
{
foreach (var observer in observers)
{
if (!loc.HasValue)
observer.OnError(new MessageUnknownException());
else
observer.OnNext(loc.Value);
}
}
public void EndTransmission()
{
foreach (var observer in observers.ToArray())
if (observers.Contains(observer))
observer.OnCompleted();
observers.Clear();
}
}
public class MessageUnknownException : Exception
{
internal MessageUnknownException()
{
}
}
public class Inspector : IObserver<Message>
{
private IDisposable unsubscriber;
private string instName;
public Inspector(string name)
{
this.instName = name;
}
public string Name
{
get
{
return this.instName;
}
}
public virtual void Subscribe(IObservable<Message> provider)
{
if (provider != null)
unsubscriber = provider.Subscribe(this);
}
public virtual void OnCompleted()
{
Console.WriteLine("The headquarters has completed transmitting data to {0}.", this.Name);
this.Unsubscribe();
}
public virtual void OnError(Exception e)
{
Console.WriteLine("{0}: Cannot get message from headquarters.", this.Name);
}
public virtual void OnNext(Message value)
{
Console.WriteLine("{1}: Message I got from headquarters: {0}", value.Text, this.Name);
}
public virtual void Unsubscribe()
{
unsubscriber.Dispose();
}
}
public class Program
{
public static void Main(string[] args)
{
Inspector inspector1 = new Inspector("Greg Lestrade");
Inspector inspector2 = new Inspector("Sherlock Holmes");
Headquarters headquarters = new Headquarters();
inspector1.Subscribe(headquarters);
inspector2.Subscribe(headquarters);
headquarters.SendMessage(new Message("Catch Moriarty!"));
headquarters.EndTransmission();
Console.ReadKey();
}
}
另一个建议—您可能想要考虑为使用IObservable
的任何代码利用响应式扩展库。nuget包是Rx-Main,它的主页在这里:http://msdn.microsoft.com/en-us/data/gg577609.aspx
更新:ReactiveX已经被翻译成许多平台和语言,现在作为一个开源项目进行管理。这是登陆页面。
这将为您节省大量的样板代码。这里有一个超级简单的例子:
var hq = new Subject<string>();
var inspectorSubscription = hq.Subscribe(
m => Console.WriteLine("Inspector received: " + m));
var subInspectorSubscription = hq.Subscribe(
m => Console.WriteLine("Sub Inspector received: " + m));
hq.OnNext("Catch Moriarty!");
输出:
Inspector received: Catch Moriarty!
Sub Inspector received: Catch Moriarty!
响应式扩展是一个很大的主题,也是一个非常强大的库——值得研究。我推荐上面链接的动手实验。
你可能想要在你的Inspector, SubInspector实现中嵌入这些订阅,以更紧密地反映你的代码。但希望这能让你了解如何使用Rx