I am using the observer pattern to add and remove subscribers from a newsletter using events.
I'm not sure how to approach what I'm trying to do. Is it possible to add a subscriber using an event and how?
The console is operated by a form with buttons so when the button is clicked it will add subscribers and when the remove button is clicked it will remove a subscriber, on the form, there is also a button to post a newsletter which will post a newsletter for each subscriber.
This is what I have managed to get so far:
class Program
{
//[STAThread]
static void Main(string[] args)
{
SoftwareRevolution softrev = new Ass_3._1.SoftwareRevolution();
ConsoleOutput First = new ConsoleOutput(softrev);
softrev.Datetime = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);
Application.Run(new InputForm());
}
}
public delegate void NotifyMe(string Value);
class ConsoleOutput : IEventsObserver
{
IEventsSubject IEventsSubject;
public ConsoleOutput(IEventsSubject IEventsSubject)
{
this.IEventsSubject = IEventsSubject;
this.IEventsSubject.Notifier += new Ass_3._1.NotifyMe(UpdateNews);
}
public void UpdateNews(string info)
{
Console.WriteLine(info);
}
}
interface IEventsObserver
{
void UpdateNews(string info);
}
interface IEventsSubject
{
event NotifyMe Notifier;
}
class SoftwareRevolution : IEventsSubject
{
List<IEventsObserver> Readers = new List<IEventsObserver>();
private string datetime;
public string Datetime
{
get
{
return datetime;
}
set
{
datetime = value;
Notifier(datetime);
}
}
public event NotifyMe Notifier;
}
The object which issues a newsletter, should have an event which fires when a newsletter issues. Then all subscribes which has subscribed for that event will receive it.
Distribution of event will be done without having such list in publisher class. In fact the delegate implementation in C# takes care of that and there is an invokation list behind the event delegate.
Usually the Publisher doesn't need to keep list of Subscriber object itself and if you need such list, it's better to keep it in a SubscriptionManager.
The subscription manager, subscribes and unsubscribes the subscribers to the event of publisher. It also can keep a list of subscribers.
Example
The Newsletter class contains some fields which represents a newsletter:
public class Newsletter
{
public string Content;
}
The NewsLetterPublishedEventArgs contains information about published newsletter:
public class NewsletterPublishedEventArgs : EventArgs
{
public Newsletter Newsletter { get; set; }
}
The Publisher class published the newsletter and raises an event after publishing:
public class Publisher
{
public event EventHandler<NewsletterPublishedEventArgs> NewsLetterPublished;
public void PublishNewsLetter()
{
var newsLetter = new Newsletter() { Content = $"New publish at {DateTime.Now}" };
NewsLetterPublished?.Invoke(this,
new NewsletterPublishedEventArgs() { Newsletter = newsLetter });
}
}
The Subscriber class has a method which allows it to receive NewsLetterPublished notification:
public class Subscriber
{
public string Name { get; set; }
public void ReceiveNewsLetter(object sender, NewsletterPublishedEventArgs e)
{
MessageBox.Show(e.Newsletter.Content);
}
}
At the end, SubscriptionManager class subscribes and unsubscribes subscribers to the publisher:
public class SubscriptionManager
{
public Publisher Publisher => new Publisher();
private List<Subscriber> subscribers;
public void Subscribe(Subscriber s)
{
if (!subscribers.Contains(s))
{
subscribers.Add(s);
Publisher.NewsLetterPublished += s.ReceiveNewsLetter;
}
}
public void Unsubscribe(Subscriber s)
{
if (subscribers.Contains(s))
{
subscribers.Remove(s);
Publisher.NewsLetterPublished -= s.ReceiveNewsLetter;
}
}
}
Note
To keep thing simple I created a simple example to just demonstrate the logic for learning purpose. In a real world example, you need to use interfaces, generic classes and dependency injection.
Related
How can ConnectionManager get expiredRegistrationId that was captured in AndroidPush class?
Am I doing this the wrong way?
Any suggestions on how I may improve my solution?
Is there any pattern I could follow?
Solution : Managers
public class ConnectionManger
{
private readonly IPushManager pushManager = new PushManager();
public void NotifyAppUser(List<PushNotificationSubscription> regIds, Alert alert)
{
pushManager.PushNotification(regIds, alert);
var expiredRegistrationId = ??
}
}
Solution : PushNotification
public class PushManager : IPushManager
{
public void PushNotification(List<PushNotificationSubscription> registeredPhone, Alert alert)
{
AndroidPush androidPush = new AndroidPush();
androidPush.Push(alert, registeredPhone);
}
}
public class AndroidPush : IPushNotificationStrategy
{
public void Push(Alert alert, List<string> registrationIds)
{
// Wait for GCM server
#region GCM Events
gcmBroker.OnNotificationFailed += (notification, aggregateEx) =>
{
var expiredRegistrationId = aggregateEx.OldId;
Q: How do i pass expiredRegistrationId to ConnectionManager class?
};
}
}
You have .NET as common playground so there are several options
Assuming:
you by solutions mean separate dll´s
you need to return a list of strings ( from the original question )
your code is keeping gcmBroker alive so the OnNotificationFailed event can fire
then this should work:
Change your signature in the IPushNotificationStrategy interface to
List<string> Push(Alert alert, List<string> registrationIds)
Add this event to your IPushManager interface:
event Action<List<string>> ExpiredRegs;
Implement and invoke this event from PushManager:
public event Action<List<string>> ExpiredRegs;
// call this when Push returns some expiredRegs :
void OnExpiredRegs(List<string> expiredRegs) => ExpiredRegs?.Invoke(expiredRegs);
Subscribe to the event in ConnectionManger:
pushManager.ExpiredRegs += OnExpiredRegs;
void OnExpiredRegs(List<string> expiredRegs)
{
// whatever you need to do
}
public class RSensor : IRSensor
{
public RSensorType SensorType { get; protected set; }
public event EventHandler ConnectionLost;
public void Configure(Stream input, Stream output, RSensorType type, ISensorReciever reciever)
{
throw new NotImplementedException();
}
public RSensor()
{
}
}
I have a class RSensor that has an EventHandler ConnectionLost which will inform me when the connection goes down.
I have another class ConnectionManager that somehow needs to handle when the connection goes down. I have created a dummy function void HandleConnectionLost()
in this class. How do I trigger this function when the EventHandler ConnectionLost from RSensor class is triggered.
public class ConnectionManager
{
ActiveList m_ActiveList;
Dictionary<IRionSensor, VSManager> m_ConnectionManager;
class VehicleStreamManager
{
public IVehicle Vehicle { get; set; }
public NetworkStream AStream { get; set; }
public NetworkStream BStream { get; set; }
}
ConnectionManager(ActiveExercise exercise)
{
m_ActiveList = exercise;
m_ConnectionManager = new Dictionary<IRSensor, VehicleStreamManager>();
}
void Connect()
{
List<VehicleStreamManager> vsmList;
VehicleStreamManager vsm;
vsm = InitiateAVehicleConnections();
m_ConnectionManager.Add(null, vsm);
vsmList = InitiateBVehicleConnections();
foreach(var item in vsmList)
{
RSensor fsensor = new RSensor();
fsensor.Configure(item.AStream, item.BStream, RSensorType.RSensor_Both, null);
m_ConnectionManager.Add(fsensor, item);
}
}
void HandleConnectionLost()
{
//Do some stuff
}
}
}
You need to redefine your HandleConnectionLost handler slightly, so that it conforms to an EventHandler signature:
void HandleConnectionLost(object sender, EventArgs args)
{
// Do stuff here
}
Then, in your ConnectionManager loop that instantiates sensors, you need to wire up the event handlers:
foreach(var item in vsmList)
{
RSensor fsensor = new RSensor();
fsensor.Configure(item.AStream, item.BStream,
RSensorType.RSensor_Both, null);
fsensor.ConnectionLost += HandleConnectionLost;
m_ConnectionManager.Add(fsensor, item);
}
This way, you handler will be triggered whenever one of the sensors loses the connection.
You are not showing the code that does this, but you said that ConnectionLost event will inform me when the connection goes down. I take this to mean that there is code present that raises the event already. If not, let me know and I'll extend the example.
However, the sensor must rely on some kind of external notification of the connection being lost - it will likely rely on a lower-level infrastructure.
I'm in a situation where I have to use 3rd party library that contains a lot of events and is imho not very well written. It fires up events that I have to handle in my code, but I'm trying to abstract it away (to be able to unit test rest of my code dependent on that library) so I need an adapter. The problem is that some of the events are of delegate type that take ref parameters. Here's an example of how the 3rd party library looks like:
delegate void AdapteeEventHandler1(SpecificAdaptee sender, int a, int b);
delegate void AdapteeEventHandler2(SpecificAdaptee sender, ref int a); // problematic delegate
class SpecificAdaptee
{
public event AdapteeEventHandler1 Event1;
public event AdapteeEventHandler2 Event2; // problematic event
/// <summary>Exercise Event1</summary>
public void FireEvent1()
{
Event1?.Invoke(this, 1, 2);
}
/// <summary>Exercise Event2</summary>
public void FireEvent2()
{
int a = 42;
Event2?.Invoke(this, ref a);
}
}
To show how I am abstracting regular event taking list of parameters, it contains Event1 of type AdapteeEventHandler1. The problematic type is AdapteeEventHandler2, but let me show first how I am going about adapting the whole thing:
#region AdaptedEventArgs
class AdaptedEventArgs1 : EventArgs
{
public int A { get; set; }
public int B { get; set; }
}
class AdaptedEventArgs2 : EventArgs
{
public int A { get; set; }
}
#endregion
/// <summary>These represent an abstraction layer between SpecificAdaptee and our own code</summary>
class Adaptor
{
private readonly SpecificAdaptee _specificAdaptee;
/// <summary>Maintains relationship between the event triggered by SpecificAdaptee and the adapted event.</summary>
private readonly IAdaptedEventHandlerManager _adaptedEventHandlerManager;
public Adaptor(SpecificAdaptee specificAdaptee, IAdaptedEventHandlerManager adaptedEventHandlerManager)
{
_specificAdaptee = specificAdaptee;
_adaptedEventHandlerManager = adaptedEventHandlerManager;
}
#region Events
/// <summary>Adapts SpecificAdaptee.Event1</summary>
public event EventHandler<AdaptedEventArgs1> AdaptedEvent1
{
add
{
_specificAdaptee.Event1 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler1>(value,
(sender, a, b) => value.Invoke(this, new AdaptedEventArgs1 { A = a, B = b }));
}
remove
{
_specificAdaptee.Event1 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler1>(value);
}
}
/// <summary>Adapts SpecificAdaptee.Event2</summary>
public event EventHandler<AdaptedEventArgs2> AdaptedEvent2
{
add
{
/* !!! ERROR HERE !!! */
_specificAdaptee.Event2 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler2>(value,
(sender, a) => value.Invoke(this, new AdaptedEventArgs2 { A = a }));
}
remove
{
_specificAdaptee.Event2 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler2>(value);
}
}
#endregion
}
So what is happening here is that when I register an event handler to Adaptor.AdaptedEvent1 I am wrapping EventHandler<AdaptedEventArgs1> in AdapteeEventHandler1 and register it to SpecificAdaptee.Event1, also converting the AdaptedEventArgs1 to list of parameters required by AdapteeEventHandler1. This way user can register to events of Adaptor that will be fired when SpecificAdaptee fires its own events. Next I will post a program that exercises this but note that the problem is in AdaptedEvent2, where I would like to do things in an analogous manner, but I don't know how to deal with the ref parameter (there is a syntax error in add accessor of AdaptedEvent2.
Here is a console application exercising the project:
class Program
{
public static void Main(string[] args)
{
var specific = new SpecificAdaptee();
var adapter = new Adaptor(specific, new AdaptedEventHandlerManager());
adapter.AdaptedEvent1 += OnAdaptedEvent1;
adapter.AdaptedEvent2 += OnAdaptedEvent2;
specific.FireEvent1();
specific.FireEvent2();
Console.ReadLine();
}
private static void OnAdaptedEvent1(object sender, AdaptedEventArgs1 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent1)}({sender}, {args.A}, {args.B})");
}
private static void OnAdaptedEvent2(object sender, AdaptedEventArgs2 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent2)}({sender}, {args.A})");
}
}
So that's how it's supposed to work. I register to events of my Adaptor that I have in my code, and events get fired when the 3rd party library (SpecificAdaptee) fires its own events (here in this example, triggered by calling specific.FireEvent1() and 2).
For completeness, so you can try it yourself I include code for AdaptedEventHandlerManager that maps adapted event handlers to SpecificAdaptee's handlers, so I can register and unregister multiple event handlers like I normally would do:
interface IAdaptedEventHandlerManager
{
TSpecificEventHandler RegisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler,
TSpecificEventHandler specificEventHandler);
TSpecificEventHandler UnregisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler)
where TSpecificEventHandler : class;
}
class AdaptedEventHandlerManager : IAdaptedEventHandlerManager
{
/// <summary>
/// Remembers relation between the specific handler and general handler. Important when unsubscribing from
/// events. Key is the general event handler we are registering to events of this class. Value are specific
/// event handlers.
/// </summary>
private readonly Dictionary<object, List<object>> _eventHandlers =
new Dictionary<object, List<object>>();
public TSpecificEventHandler RegisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler,
TSpecificEventHandler specificEventHandler)
{
List<object> eventHandlerList;
if (!_eventHandlers.TryGetValue(adaptedEventHandler, out eventHandlerList))
{
eventHandlerList = new List<object> { specificEventHandler };
_eventHandlers.Add(adaptedEventHandler, eventHandlerList);
}
else
{
eventHandlerList.Add(specificEventHandler);
}
return specificEventHandler;
}
public TSpecificEventHandler UnregisterEventHandler<TSpecificEventHandler>(object adaptedEventHandler)
where TSpecificEventHandler : class
{
List<object> eventHandlerList;
if (!_eventHandlers.TryGetValue(adaptedEventHandler, out eventHandlerList))
{
return null;
}
var eventHandler = eventHandlerList.FirstOrDefault();
if (eventHandler != null)
{
eventHandlerList.Remove(eventHandler);
}
if (!eventHandlerList.Any())
{
_eventHandlers.Remove(adaptedEventHandler);
}
return eventHandler as TSpecificEventHandler;
}
}
This basically remembers in a dictionary the adapted event handler, and the list of SpecificAdaptee's handlers.
So my question: is there a way to adapt events taking ref parameters without retracting to custom delegate type that takes a ref parameter, so I can use standard EventHandler<> class with custom EventArgs descendant?
I realise it's quite a handful of code so please let me know if something is not clear. Thanks in advance.
ref parameter in the event is meant to set from the subscribers. Though it's a bad idea, the api which you're using works based on that.
You can take all the pain in the adapter class and make it work such that consumers are not polluted by the ref parameter. They can continue to use EventArgs style events.
public event EventHandler<AdaptedEventArgs2> AdaptedEvent2
{
add
{
_specificAdaptee.Event2 += _adaptedEventHandlerManager.RegisterEventHandler<AdapteeEventHandler2>(value,
(SpecificAdaptee sender, ref int a) =>
{
var args = new AdaptedEventArgs2 { A = a };
value.Invoke(this, args);
a = args.A;
});
}
remove
{
_specificAdaptee.Event2 -= _adaptedEventHandlerManager.UnregisterEventHandler<AdapteeEventHandler2>(value);
}
}
After the event is executed, we set the value of A to the ref parameter a. This simulates the behavior of ref parameter and also abstracts it under the adapter class. If A is changed in the event handler, it will be reflected in the SpecificAdaptee class too.
To show how this works like a ref parameter:
class SpecificAdaptee
{
...
public void FireEvent2()
{
int a = 42;
if (Event2 != null)
Event2(this, ref a);
Console.WriteLine("A value after the event is {0}", a);
}
}
private static void OnAdaptedEvent2(object sender, AdaptedEventArgs2 args)
{
Console.WriteLine($"{nameof(OnAdaptedEvent2)}({sender}, {args.A})");
args.A = 15;
}
This prints:
A value after the event is 15
PS: For brevity I've added only the parts of your program which needs a change.
I'm used to using delegate EventHandler for event callbacks but now I'm attempting to use event Action for invoking events. I couldn't find much info on how this can be used properly anywhere so I'm hoping someone can point me in the right direction.
I have an Action event handler that handles string objects. In my subscriber class I have public event Action<string> UploadProgress;. The event handler is invoked like this:
UploadProgress.Invoke(string.Format("sending file data {0:0.000}%", (bytesSoFar * 100.0f) / totalToUpload));
The listener class is subscribed to this event as below:
uploadFile.UploadProgress += uploadFile_UploadProgress;
void uploadFile_UploadProgress(string obj)
{
var prog = obj;
}
When the event is invoked, I get System.NullReferenceException: Object reference not set to an instance of an object. I'm not sure what I need to change in the subscriber class to avoid this error. Can someone tell me the proper way to use event Action or provide me the link to where I can read up on it? I know how to use the normal Action but confused about declaring it as an event. Any help is appreciated.
This way is much better, send bytesToUpload and totalToUpload through event, instead of the whole Action (right sample):
internal class Program
{
private static void Main(string[] args)
{
SomeClass someClass = new SomeClass();
someClass.UploadProgress += SomeClass_UploadProgress;
someClass.DoSomeUpload();
}
private static void SomeClass_UploadProgress(object sender, UploadEventArgs e)
{
string s = string.Format("sending file data {0:0.000}%", (e.BytesSoFar * 100.0f) / e.TotalToUpload);
Console.WriteLine(s);
}
}
public class UploadEventArgs : EventArgs
{
public float BytesSoFar { get; set; }
public float TotalToUpload { get; set; }
}
public class SomeClass
{
public event EventHandler<UploadEventArgs> UploadProgress;
public void DoSomeUpload()
{
if (UploadProgress != null)
{
UploadEventArgs e = new UploadEventArgs();
e.BytesSoFar = 123f;
e.TotalToUpload = 100000f;
UploadProgress.Invoke(this, e);
}
}
}
I recently started digging into C# but I can't by my life figure out how delegates work when implementing the observer/observable pattern in the language.
Could someone give me a super-simple example of how it is done? I have googled this, but all of the examples I found were either too problem-specific or too "bloated".
The observer pattern is usually implemented with events.
Here's an example:
using System;
class Observable
{
public event EventHandler SomethingHappened;
public void DoSomething() =>
SomethingHappened?.Invoke(this, EventArgs.Empty);
}
class Observer
{
public void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}
class Test
{
static void Main()
{
Observable observable = new Observable();
Observer observer = new Observer();
observable.SomethingHappened += observer.HandleEvent;
observable.DoSomething();
}
}
See the linked article for a lot more detail.
Note that the above example uses C# 6 null-conditional operator to implement DoSomething safely to handle cases where SomethingHappened has not been subscribed to, and is therefore null. If you're using an older version of C#, you'd need code like this:
public void DoSomething()
{
var handler = SomethingHappened;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
In this model, you have publishers who will do some logic and publish an "event."
Publishers will then send out their event only to subscribers who have subscribed to receive the specific event.
In C#, any object can publish a set of events to which other applications can subscribe.
When the publishing class raises an event, all the subscribed applications are notified.
The following figure shows this mechanism.
Simplest Example possible on Events and Delegates in C#:
code is self explanatory, Also I've added the comments to clear out the code.
using System;
public class Publisher //main publisher class which will invoke methods of all subscriber classes
{
public delegate void TickHandler(Publisher m, EventArgs e); //declaring a delegate
public TickHandler Tick; //creating an object of delegate
public EventArgs e = null; //set 2nd paramter empty
public void Start() //starting point of thread
{
while (true)
{
System.Threading.Thread.Sleep(300);
if (Tick != null) //check if delegate object points to any listener classes method
{
Tick(this, e); //if it points i.e. not null then invoke that method!
}
}
}
}
public class Subscriber1 //1st subscriber class
{
public void Subscribe(Publisher m) //get the object of pubisher class
{
m.Tick += HeardIt; //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e) //subscriber class method
{
System.Console.WriteLine("Heard It by Listener");
}
}
public class Subscriber2 //2nd subscriber class
{
public void Subscribe2(Publisher m) //get the object of pubisher class
{
m.Tick += HeardIt; //attach listener class method to publisher class delegate object
}
private void HeardIt(Publisher m, EventArgs e) //subscriber class method
{
System.Console.WriteLine("Heard It by Listener2");
}
}
class Test
{
static void Main()
{
Publisher m = new Publisher(); //create an object of publisher class which will later be passed on subscriber classes
Subscriber1 l = new Subscriber1(); //create object of 1st subscriber class
Subscriber2 l2 = new Subscriber2(); //create object of 2nd subscriber class
l.Subscribe(m); //we pass object of publisher class to access delegate of publisher class
l2.Subscribe2(m); //we pass object of publisher class to access delegate of publisher class
m.Start(); //starting point of publisher class
}
}
Output:
Heard It by Listener
Heard It by Listener2
Heard It by Listener
Heard It by Listener2
Heard It by Listener
.
.
.
(infinite times)
Here's a simple example:
public class ObservableClass
{
private Int32 _Value;
public Int32 Value
{
get { return _Value; }
set
{
if (_Value != value)
{
_Value = value;
OnValueChanged();
}
}
}
public event EventHandler ValueChanged;
protected void OnValueChanged()
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
}
public class ObserverClass
{
public ObserverClass(ObservableClass observable)
{
observable.ValueChanged += TheValueChanged;
}
private void TheValueChanged(Object sender, EventArgs e)
{
Console.Out.WriteLine("Value changed to " +
((ObservableClass)sender).Value);
}
}
public class Program
{
public static void Main()
{
ObservableClass observable = new ObservableClass();
ObserverClass observer = new ObserverClass(observable);
observable.Value = 10;
}
}
Note:
This violates a rule in that I don't unhook the observer from the observable, this is perhaps good enough for this simple example, but make sure you don't keep observers hanging off of your events like that. A way to handle this would be to make ObserverClass IDisposable, and let the .Dispose method do the opposite of the code in the constructor
No error-checking performed, at least a null-check should be done in the constructor of the ObserverClass
I've tied together a couple of the great examples above (thank you as always to Mr. Skeet and Mr. Karlsen) to include a couple of different Observables and utilized an interface to keep track of them in the Observer and allowed the Observer to to "observe" any number of Observables via an internal list:
namespace ObservablePattern
{
using System;
using System.Collections.Generic;
internal static class Program
{
private static void Main()
{
var observable = new Observable();
var anotherObservable = new AnotherObservable();
using (IObserver observer = new Observer(observable))
{
observable.DoSomething();
observer.Add(anotherObservable);
anotherObservable.DoSomething();
}
Console.ReadLine();
}
}
internal interface IObservable
{
event EventHandler SomethingHappened;
}
internal sealed class Observable : IObservable
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
var handler = this.SomethingHappened;
Console.WriteLine("About to do something.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
internal sealed class AnotherObservable : IObservable
{
public event EventHandler SomethingHappened;
public void DoSomething()
{
var handler = this.SomethingHappened;
Console.WriteLine("About to do something different.");
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
internal interface IObserver : IDisposable
{
void Add(IObservable observable);
void Remove(IObservable observable);
}
internal sealed class Observer : IObserver
{
private readonly Lazy<IList<IObservable>> observables =
new Lazy<IList<IObservable>>(() => new List<IObservable>());
public Observer()
{
}
public Observer(IObservable observable) : this()
{
this.Add(observable);
}
public void Add(IObservable observable)
{
if (observable == null)
{
return;
}
lock (this.observables)
{
this.observables.Value.Add(observable);
observable.SomethingHappened += HandleEvent;
}
}
public void Remove(IObservable observable)
{
if (observable == null)
{
return;
}
lock (this.observables)
{
observable.SomethingHappened -= HandleEvent;
this.observables.Value.Remove(observable);
}
}
public void Dispose()
{
for (var i = this.observables.Value.Count - 1; i >= 0; i--)
{
this.Remove(this.observables.Value[i]);
}
}
private static void HandleEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happened to " + sender);
}
}
}
Applying the Observer Pattern with delegates and events in c# is named "Event Pattern" according to MSDN which is a slight variation.
In this Article you will find well structured examples of how to apply the pattern in c# both the classic way and using delegates and events.
Exploring the Observer Design Pattern
public class Stock
{
//declare a delegate for the event
public delegate void AskPriceChangedHandler(object sender,
AskPriceChangedEventArgs e);
//declare the event using the delegate
public event AskPriceChangedHandler AskPriceChanged;
//instance variable for ask price
object _askPrice;
//property for ask price
public object AskPrice
{
set
{
//set the instance variable
_askPrice = value;
//fire the event
OnAskPriceChanged();
}
}//AskPrice property
//method to fire event delegate with proper name
protected void OnAskPriceChanged()
{
AskPriceChanged(this, new AskPriceChangedEventArgs(_askPrice));
}//AskPriceChanged
}//Stock class
//specialized event class for the askpricechanged event
public class AskPriceChangedEventArgs : EventArgs
{
//instance variable to store the ask price
private object _askPrice;
//constructor that sets askprice
public AskPriceChangedEventArgs(object askPrice) { _askPrice = askPrice; }
//public property for the ask price
public object AskPrice { get { return _askPrice; } }
}//AskPriceChangedEventArgs
/**********************Simple Example ***********************/
class Program
{
static void Main(string[] args)
{
Parent p = new Parent();
}
}
////////////////////////////////////////////
public delegate void DelegateName(string data);
class Child
{
public event DelegateName delegateName;
public void call()
{
delegateName("Narottam");
}
}
///////////////////////////////////////////
class Parent
{
public Parent()
{
Child c = new Child();
c.delegateName += new DelegateName(print);
//or like this
//c.delegateName += print;
c.call();
}
public void print(string name)
{
Console.WriteLine("yes we got the name : " + name);
}
}
I did't want to change my source code to add additional observer , so I have written following simple example:
//EVENT DRIVEN OBSERVER PATTERN
public class Publisher
{
public Publisher()
{
var observable = new Observable();
observable.PublishData("Hello World!");
}
}
//Server will send data to this class's PublishData method
public class Observable
{
public event Receive OnReceive;
public void PublishData(string data)
{
//Add all the observer below
//1st observer
IObserver iObserver = new Observer1();
this.OnReceive += iObserver.ReceiveData;
//2nd observer
IObserver iObserver2 = new Observer2();
this.OnReceive += iObserver2.ReceiveData;
//publish data
var handler = OnReceive;
if (handler != null)
{
handler(data);
}
}
}
public interface IObserver
{
void ReceiveData(string data);
}
//Observer example
public class Observer1 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}
public class Observer2 : IObserver
{
public void ReceiveData(string data)
{
//sample observers does nothing with data :)
}
}
Something like this:
// interface implementation publisher
public delegate void eiSubjectEventHandler(eiSubject subject);
public interface eiSubject
{
event eiSubjectEventHandler OnUpdate;
void GenereteEventUpdate();
}
// class implementation publisher
class ecSubject : eiSubject
{
private event eiSubjectEventHandler _OnUpdate = null;
public event eiSubjectEventHandler OnUpdate
{
add
{
lock (this)
{
_OnUpdate -= value;
_OnUpdate += value;
}
}
remove { lock (this) { _OnUpdate -= value; } }
}
public void GenereteEventUpdate()
{
eiSubjectEventHandler handler = _OnUpdate;
if (handler != null)
{
handler(this);
}
}
}
// interface implementation subscriber
public interface eiObserver
{
void DoOnUpdate(eiSubject subject);
}
// class implementation subscriber
class ecObserver : eiObserver
{
public virtual void DoOnUpdate(eiSubject subject)
{
}
}
.
observer pattern C# with event
.
link to the repository