Inter-object event messaging (Mediator Pattern?) (very long sorry)

H

halekio

Hi all,

Please bear with me as I've only started programming in C# 2 weeks ago
and this is my first contact with OOP.

I ran into a situation where I needed to catch an event in an object
that had no connection or reference to the object that triggered it.

It goes something like this: (not syntactically correct..it's just for
the idea)

main()
{ A a;
C c;
a.Run();
}

class A
{ B b;
C c;

Run()
{ // Trigger the Event here}
} // class

class B
{ C c;
}

class C
{ // Catch and handle the event here
}

Which means that the event would be handled by the 3 instances of C.

From My research I gathered that I should be using something called
the "Mediator Pattern".
Unfortunately I could not find a working example of this.

Also, from what I was able to understand, to make it work with this
pattern would require that I derive class C from an abstract
"participant". Is that right ?

I then kind of gave up on trying to make it work with this pattern
(out of frustration at my failures) and proceeded to try and implement
something that I was a bit more familiar with (from my backgroung with
PCS):
The Publish / Subscribe model (is that also known as a pattern?)


I was pleasantly surprised that it worked.
Here's my working implementation:

All classes use the following:
using System;
using System.Collections.Generic;
using System.Text;

With the class Dispatcher also using:
using System.Collections;


class Program
{
static void Main(string[] args)
{
A a = new A();
C c = new C("C1");

for(int i = 1; i <= 3; i++)
{
a.Run(i);
}
Console.ReadKey();
}
}

class A
{
B b = new B();
C c = new C("C2");

public void Run(int i)
{
Dispatcher.Publish("MyEvent", "Hello #" + i.ToString());
}
}

class B
{
C c = new C("C3");
}

class C
{
private string name;

public C(string name)
{
this.name = name;
Dispatcher.Subscribe("MyEvent", OnMyEvent);
}

public void OnMyEvent(object appEventParams)
{
string textReceived = (string)appEventParams;
Console.WriteLine(textReceived + " received in " + name);
}

}

public delegate void AppEventHandler(object appEventParams);

static class Dispatcher
{
private static Hashtable registry = new Hashtable();

public static void Subscribe(string appEvent, AppEventHandler
appEventHandler)
{
Subscription(appEvent, appEventHandler, true);
}

public static void Unsubscribe(string appEvent,
AppEventHandler appEventHandler)
{
Subscription(appEvent, appEventHandler, false);
}

private static void Subscription(string appEvent,
AppEventHandler appEventHandler, bool add)
{
ArrayList list;

if (add)
{
if (registry[appEvent] == null)
registry.Add(appEvent, new ArrayList());

list = (ArrayList)registry[appEvent];
list.Add(appEventHandler);
}
else
{
if (registry[appEvent] != null)
{
list = (ArrayList)registry[appEvent];
list.Remove(appEventHandler);
}
}
}

public static void Publish(string appEvent, object
appEventParams)
{
ArrayList list;
AppEventHandler appEventHandler;

if (registry[appEvent] != null)
{
list = (ArrayList)registry[appEvent];

for (int i = 0; i < list.Count; i++)
{
appEventHandler = (AppEventHandler)list;
if (appEventHandler != null)
appEventHandler(appEventParams);
}
}
}
}


The ouput is:
Hello #1 received in C3
Hello #1 received in C2
Hello #1 received in C1
Hello #2 received in C3
Hello #2 received in C2
Hello #2 received in C1
Hello #3 received in C3
Hello #3 received in C2
Hello #3 received in C1

Here are my questions (about time you'll say...sorry about that too
long preambule):

1) Is 'this" somehow a valid implementation of the Mediator pattern
and if not, it is known under another name ? (I hope it's not one of
those anti-pattern)

2) If it's not a valid implementation of the Mediator pattern (or
another "good" pattern), is there any reason why you would advise
"against" this approach. Did I miss an obvious flaw ? Did I do a big
no-no ?

3) Could you "please" (pretty, pretty please) give me a valid
implementation of the Mediator pattern that would give me the exact
same behavior as in my example. (If possible please give me working
code)

4) Any other comments, good of bad, that you think might help me with
this problem.

Thanks a lot in advance.
 
L

Lebesgue

I don't have time to read through and think about your whole question but a
working mediator pattern implementation in C# is to be found here:
http://www.dofactory.com/Patterns/PatternMediator.aspx#csharp - don't know
if it does exactly the same your code does.
Maybe it will clarify something you need to have clarified.

Hi all,

Please bear with me as I've only started programming in C# 2 weeks ago
and this is my first contact with OOP.

I ran into a situation where I needed to catch an event in an object
that had no connection or reference to the object that triggered it.

It goes something like this: (not syntactically correct..it's just for
the idea)

main()
{ A a;
C c;
a.Run();
}

class A
{ B b;
C c;

Run()
{ // Trigger the Event here}
} // class

class B
{ C c;
}

class C
{ // Catch and handle the event here
}

Which means that the event would be handled by the 3 instances of C.

From My research I gathered that I should be using something called
the "Mediator Pattern".
Unfortunately I could not find a working example of this.

Also, from what I was able to understand, to make it work with this
pattern would require that I derive class C from an abstract
"participant". Is that right ?

I then kind of gave up on trying to make it work with this pattern
(out of frustration at my failures) and proceeded to try and implement
something that I was a bit more familiar with (from my backgroung with
PCS):
The Publish / Subscribe model (is that also known as a pattern?)


I was pleasantly surprised that it worked.
Here's my working implementation:

All classes use the following:
using System;
using System.Collections.Generic;
using System.Text;

With the class Dispatcher also using:
using System.Collections;


class Program
{
static void Main(string[] args)
{
A a = new A();
C c = new C("C1");

for(int i = 1; i <= 3; i++)
{
a.Run(i);
}
Console.ReadKey();
}
}

class A
{
B b = new B();
C c = new C("C2");

public void Run(int i)
{
Dispatcher.Publish("MyEvent", "Hello #" + i.ToString());
}
}

class B
{
C c = new C("C3");
}

class C
{
private string name;

public C(string name)
{
this.name = name;
Dispatcher.Subscribe("MyEvent", OnMyEvent);
}

public void OnMyEvent(object appEventParams)
{
string textReceived = (string)appEventParams;
Console.WriteLine(textReceived + " received in " + name);
}

}

public delegate void AppEventHandler(object appEventParams);

static class Dispatcher
{
private static Hashtable registry = new Hashtable();

public static void Subscribe(string appEvent, AppEventHandler
appEventHandler)
{
Subscription(appEvent, appEventHandler, true);
}

public static void Unsubscribe(string appEvent,
AppEventHandler appEventHandler)
{
Subscription(appEvent, appEventHandler, false);
}

private static void Subscription(string appEvent,
AppEventHandler appEventHandler, bool add)
{
ArrayList list;

if (add)
{
if (registry[appEvent] == null)
registry.Add(appEvent, new ArrayList());

list = (ArrayList)registry[appEvent];
list.Add(appEventHandler);
}
else
{
if (registry[appEvent] != null)
{
list = (ArrayList)registry[appEvent];
list.Remove(appEventHandler);
}
}
}

public static void Publish(string appEvent, object
appEventParams)
{
ArrayList list;
AppEventHandler appEventHandler;

if (registry[appEvent] != null)
{
list = (ArrayList)registry[appEvent];

for (int i = 0; i < list.Count; i++)
{
appEventHandler = (AppEventHandler)list;
if (appEventHandler != null)
appEventHandler(appEventParams);
}
}
}
}


The ouput is:
Hello #1 received in C3
Hello #1 received in C2
Hello #1 received in C1
Hello #2 received in C3
Hello #2 received in C2
Hello #2 received in C1
Hello #3 received in C3
Hello #3 received in C2
Hello #3 received in C1

Here are my questions (about time you'll say...sorry about that too
long preambule):

1) Is 'this" somehow a valid implementation of the Mediator pattern
and if not, it is known under another name ? (I hope it's not one of
those anti-pattern)

2) If it's not a valid implementation of the Mediator pattern (or
another "good" pattern), is there any reason why you would advise
"against" this approach. Did I miss an obvious flaw ? Did I do a big
no-no ?

3) Could you "please" (pretty, pretty please) give me a valid
implementation of the Mediator pattern that would give me the exact
same behavior as in my example. (If possible please give me working
code)

4) Any other comments, good of bad, that you think might help me with
this problem.

Thanks a lot in advance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top