IObserver et IObservable en C# pour les observateurs vs délégués, événements
Tout ce que j'essaie de faire, c'est mettre en place le schéma de l'observateur.
donc, j'ai trouvé cette solution:
nous avons un quartier général de la police dont la tâche principale est d'envoyer des notifications à tous ceux qui y sont abonnés. Considérez que les classes DSP, Inspector et SubInspector sont souscrites aux quartiers généraux de la police.
utilisant des événements et des délégués j'ai écrit
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()));
}
}
et voici comment je invoqué it
var headQuarters = new HeadQuarters();
var SubInspector = new SubInspector();
var Inspector = new Inspector();
headQuarters.NewEvent += Inspector.Listen;
headQuarters.NewEvent += SubInspector.Listen;
headQuarters.RaiseANotification();
ainsi, les classes D'inspecteur et de sous-inspecteur reçoivent notification chaque fois que la fonction RaiseANotification() est invoquée.
il semble que le cadre DotNet 4, 4.5 supporte une nouvelle voie appelée IObserver et IObservable.
est-ce que quelqu'un peut me donner un exemple super simple en utilisant IObservable et IObserver pattern pour le scénario ci-dessus? J'ai googlé pour trouver seulement les exemples disponibles dans l'internet lourd et difficile à comprendre.
Ma touche: (probablement, je pense que c'est faux)
class DSP : IObserver //since it observes the headquarters ?
class PoliceHeadQuarters: IObservable // since here's where we send the notifications ?
Merci d'avance.
modifier: Quelqu'un a également dit que la documentation MSDN est également incorrecte pour IObservable @ IObservable vs Plaine des Événements ou Pourquoi Devrais-je utiliser IObservable? .
2 réponses
voici une modification de L'exemple MSDN pour s'adapter à votre cadre:
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();
}
}
une autre suggestion - vous voulez probablement envisager de tirer parti de la bibliothèque des extensions réactives pour tout code utilisant IObservable
. Le paquet nuget est Rx-Main et la page d'accueil est ici: http://msdn.microsoft.com/en-us/data/gg577609.aspx
vous économiserez beaucoup de code boilerplate. Voici un exemple très simple:
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!");
il sortira:
Inspector received: Catch Moriarty!
Sub Inspector received: Catch Moriarty!
réactif Extensions est un grand sujet, et une bibliothèque très puissante - intéressant d'étudier. Je recommande le laboratoire pratique à partir du lien ci-dessus.
vous voudriez probablement intégrer ces souscriptions dans votre inspecteur, sous-inspecteur implementatinos pour refléter plus étroitement votre code. Mais espérons que cela vous donne un aperçu de ce que vous pouvez faire avec Rx.