Passing events between different classes

T

Tom

This is probably a really basic question, but I know someone will be
able to help me. I have a single object A that contains a hash of
objects B. Each object B contains its own TCP client object containing
a connection to a server somewhere.

There is also a completely separate hash of objects C at the same
place as Object A. When I get TCP data into the TCP client I need to
let all of the object C's know about it. I Was wondering if I could
have all of the C objects register for the B events?

Tom
 
P

Peter Duniho

This is probably a really basic question, but I know someone will be
able to help me. I have a single object A that contains a hash of
objects B. Each object B contains its own TCP client object containing
a connection to a server somewhere.

There is also a completely separate hash of objects C at the same
place as Object A. When I get TCP data into the TCP client I need to
let all of the object C's know about it. I Was wondering if I could
have all of the C objects register for the B events?

Is object A at all relevant? You didn't mention it with respect to the
communication between the objects B and objects C, so for the moment I'm
essentially (mostly) ignoring your first paragraph.

Anyway, yes...you can have each object C subscribe to an event on each
object B if you like. Every time an object C is instantiated, it would
have to subscribe to every object B's event, and every time an object B is
instantiated, each object C would need some way to know so that each can
subscribe to the new object B's event.

You may want to consider a "mediator"-based design, in which there's an
intermediate class that handles the connections between objects C and
objects B. Perhaps this is object A, or maybe you will want to make
another object to do this. You don't provide enough specifics for anyone
else to suggest which is better, so you'll have to decide that for
yourself.

The way the mediator would work is that objects C would all subscribe to a
single event on the mediator, while the mediator would subscribe to each
of the objects B event. Then when the mediator receives the event raised
by any object B, it would forward that event to its own event, which would
automatically result in each object C receiving the event.

This way each object C only needs to deal with a single object (the
mediator) and does not need to concern itself with the instantiation of
new objects B, while each object B would only have a single object (the
mediator) subscribed to its own event. Also, it encapsulates the
management of dealing with instantiations of each object B into a single
class (a nice way to do that would be to make the object B class aware of
the mediator, and register itself when it's instantiated, providing a
method in the mediator that in turn subscribes the mediator to the object
B event).

Pete
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Tom said:
This is probably a really basic question, but I know someone will be
able to help me. I have a single object A that contains a hash of
objects B. Each object B contains its own TCP client object containing
a connection to a server somewhere.

There is also a completely separate hash of objects C at the same
place as Object A. When I get TCP data into the TCP client I need to
let all of the object C's know about it. I Was wondering if I could
have all of the C objects register for the B events?

You could do so, but then you will have to let each C instance know of every
B objects.

A better approach might be if A is the one that subscribe to B's and then A
will iterate in C's.

btw, how you are keeping receiving info from all those B's instances?
 
T

Tom

Hi,





You could do so, but then you will have to let each C instance know of every
B objects.

A better approach might be if A is the one that subscribe to B's and then A
will iterate in C's.

btw, how you are keeping receiving info from all those B's instances?

I guess I am confused as to the fact that in order to subscribe to an
event, you have to have an instance of the event generating class
defined in your class. X must be created in Y for Y to subscribe to X
events. How would you make a Mediator class without instantiating the
others classes in it?
 
P

Peter Duniho

I guess I am confused as to the fact that in order to subscribe to an
event, you have to have an instance of the event generating class
defined in your class. X must be created in Y for Y to subscribe to X
events.

That's not true. Can you explain why it is you think it is? Y need not
even contain a reference to X, never mind is X required to be created "in"
or "by" Y.

The only requirement is that at the point in time that Y subscribes to the
event, it have a reference to the object on which the event exists. Once
it's subscribed to the event, it no longer needs the reference to the
object.
How would you make a Mediator class without instantiating the
others classes in it?

However you like. The other classes need not be instantiated within the
mediator class.

A fairly common scenario would be to make the Mediator class a singleton..
This fits with the usual design of there always being just one Mediator,
and provides a nice, easy way to obtain a reference to the Mediator
instance (i.e. via a static method that returns the instance).

But you can put the mediator instance wherever you like, as long as those
classes that need to us it can get to it.

As a quick and dirty example (in other words, I have no idea if this will
actually compile, but hopefully it gets the point across):

// This class publishes the event that the subscribers are interested
in
public class Publisher
{
public event EventHandler TheEvent;

public Publisher()
{
// On instantiation, inform the mediator class that this
instance exists
Mediator.Instance.Register(this);
}
}

// This class mediates between the instances that publish the event
and those
// that subscribe to it
public class Mediator
{
// The mediator needs its own event that the subscribers can
subscribe to,
// rather than them subscribing to each Publisher instance's event
public event EventHandler TheEvent;

// singleton instance
private static Mediator _mediator;

// hide the constructor
private Mediator()
{
}

// accessor to get the one instance of the class
public static Mediator Instance
{
get
{
if (_mediator == null)
{
_mediator = new Mediator();
}

return _mediator;
}
}

// When the Publisher instance calls this, the Mediator subscribes
to its event
public void Register(Publisher publisher)
{
publisher.TheEvent += _MyHandler;
}

// In the handler for the event, the Mediator then raises the
event for everyone
// subscribed to it.
private void _MyHandler(object sender, EventArgs e)
{
EventHandler handler = TheEvent;

if (handler != null)
{
handler(sender, e);
}
}
}

// This is the class that is actually interested in the event that the
Publisher exposes
public class Subscriber
{
// Upon instantiation (or wherever you like) the subscriber
subscribes not to the
// Publisher's event directly, but to the Mediator's event
public Subscriber()
{
Mediator.Instance.TheEvent += _MyHandler;
}

// And of course, you ultimately need a handler that does
something real. :)
private void _MyHandler(object sender, EventArgs e)
{
// do whatever here
}
}
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Tom said:
I guess I am confused as to the fact that in order to subscribe to an
event, you have to have an instance of the event generating class
defined in your class. X must be created in Y for Y to subscribe to X
events. How would you make a Mediator class without instantiating the
others classes in it?

Please refer to the classes using the same naming you used before (A,B,C)
using X and Y now only created confusion.

A is a single object (from your first post) so it can be safe to think that
it does exist at everytime. Each tmie a new B instance is created it can get
a hold of the A instance (a Singleton class?) and can subscribe a member of
A to the event that B will raise.

The same can happen with C, each instance can get THE reference to A and
subscribe to the event that A will fire when an event from B is received. As
you can see in this implementation B is not aware of C. At the same time you
can have the instances of B & C created anywhere, not only that but you do
not need to hold a reference to neither B's nor C's !!!
 
T

Tom

Thanks Peter,

This has really clarified everything for me, I guess I was just used
to doing things a certain way...

Thanks again,
Tom
 
T

Tom

I am feeling very frusturated about this right now. The part that is
frusturating is the:

// When the Publisher instance calls this, the Mediator
subscribes
to its event
public void Register(Publisher publisher)
{
publisher.TheEvent += _MyHandler;
}


I have moved my mediator class to the utilites namespace of our
project. Both classes that need to use the mediator are in different
namespaces, but both use the utilities namespace. So that is great
and all until I get to the Register function. Based on the previous
example, show above, it looks like it needs to know about the
Publisher class. Is there a way to get around it having to know about
the publisher class? Since all my classes are USING ProgramUtils;, I
feel it would be improper to have USING MainProgram; in the utils?

Tom
 
P

Peter Duniho

[...] Based on the previous
example, show above, it looks like it needs to know about the
Publisher class. Is there a way to get around it having to know about
the publisher class?

You can do it a couple of ways:

1) Have a Publisher base class that the actual publisher class
inherits. The Publisher base class would be declared with the Mediator
class, while the actual publisher class can be declared anywhere, and the
Mediator and subscribers need not even know the actual publisher class.

2) Have a Publisher interface that the actual publisher class
implements. See above.

Pete
 
T

Tom

[...] Based on the previous
example, show above, it looks like it needs to know about the
Publisher class. Is there a way to get around it having to know about
the publisher class?

You can do it a couple of ways:

1) Have a Publisher base class that the actual publisher class
inherits. The Publisher base class would be declared with the Mediator
class, while the actual publisher class can be declared anywhere, and the
Mediator and subscribers need not even know the actual publisher class.

2) Have a Publisher interface that the actual publisher class
implements. See above.

Pete


That seemed to work great. Thanks Again!!

Tom
 

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