Wednesday, August 23, 2006

C#: Event Model and Observer pattern

Observer pattern can be made easily using C# multicast deletgates. We will define two classes Publisher and Subscriber. Publisher is the class which publish the 'event'. Subscriber class subscribes the event and whenever event is called, subscriber is notified. Subscriber can have function which can be invoked in response to event. This function is called event handler. Publisher-Subscriber model can be built on two methodologies - Pull and Push.
In Pull, subscriber has permission to 'see' data/state of Publisher.
In Push, Publisher notify subscriber with only most relevant data/state. Here I am going to implement Push Model.


//Code
       public class Publisher2
{
// EventHandler delegate is defined .NET as
// public delegate void EventHandler (object obj, EventArgs e);
public event EventHandler onTick;

private void NotifyOnTick(EventArgs e)
{
if (onTick != null)
{
onTick(this, e);
}

}

public void StartClock()
{
int tick = 1;
while (tick <= 10) { System.Threading.Thread.Sleep(1000); NotifyOnTick(new MyEventArgs(tick));
tick++;
}
}

}

public class MyEventArgs : EventArgs
{
private int tick;
public int Tick
{
get { return this.tick;}
}

public MyEventArgs(int tick)
{
this.tick = tick;
}

}

public class Subscriber2
{
private int subsriberID;
public Subscriber2(Publisher2 publisher, int id)
{
this.subsriberID = id;
publisher.onTick += new EventHandler(this.DisplayOnTick);
}
public void DisplayOnTick(object obj, EventArgs e)
{
Console.Write("Subscriber [{0}]: ", this.subsriberID);
MyEventArgs me = e as MyEventArgs;
Console.WriteLine(me.Tick.ToString());
}
public void Unsubscribe(Publisher2 publisher)
{
publisher.onTick -= new EventHandler(this.DisplayOnTick);
}
}


class Class1
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{

Publisher2 publisher = new Publisher2();
Subscriber2 sbc1 = new Subscriber2(publisher,1);
Subscriber2 sbc2 = new Subscriber2(publisher,2);
publisher.StartClock();
sbc2.Unsubscribe(publisher);
publisher.StartClock();
}
}
//Output
Subscriber [1]: 1
Subscriber [2]: 1
Subscriber [1]: 2
Subscriber [2]: 2
Subscriber [1]: 3
Subscriber [2]: 3
Subscriber [1]: 4
Subscriber [2]: 4
Subscriber [1]: 5
Subscriber [2]: 5
Subscriber [1]: 6
Subscriber [2]: 6
Subscriber [1]: 7
Subscriber [2]: 7
Subscriber [1]: 8
Subscriber [2]: 8
Subscriber [1]: 9
Subscriber [2]: 9
Subscriber [1]: 10
Subscriber [2]: 10
Subscriber [1]: 1
Subscriber [1]: 2
Subscriber [1]: 3
Subscriber [1]: 4
Subscriber [1]: 5
Subscriber [1]: 6
Subscriber [1]: 7
Subscriber [1]: 8
Subscriber [1]: 9
Subscriber [1]: 10

No comments: