.NET Forum / Languages / C# / July 2007
Passing events between different classes
|
|
Thread rating:  |
Tom - 16 Jul 2007 20:26 GMT 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
Peter Duniho - 16 Jul 2007 20:50 GMT > 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 [quoted text clipped - 5 lines] > 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
Ignacio Machin ( .NET/ C# MVP ) - 16 Jul 2007 21:26 GMT Hi,
> 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 [quoted text clipped - 5 lines] > 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?
Tom - 16 Jul 2007 21:39 GMT On Jul 16, 4:26 pm, "Ignacio Machin \( .NET/ C# MVP \)" <machin TA laceupsolutions.com> wrote:
> Hi, > [quoted text clipped - 15 lines] > > 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?
Peter Duniho - 16 Jul 2007 23:36 GMT > 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 } }
Tom - 17 Jul 2007 19:16 GMT Thanks Peter,
This has really clarified everything for me, I guess I was just used to doing things a certain way...
Thanks again, Tom
Tom - 26 Jul 2007 21:18 GMT 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
Peter Duniho - 26 Jul 2007 21:22 GMT > [...] 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
Tom - 26 Jul 2007 21:36 GMT On Jul 26, 4:22 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:
> > [...] Based on the previous > > example, show above, it looks like it needs to know about the [quoted text clipped - 12 lines] > > Pete That seemed to work great. Thanks Again!!
Tom
Ignacio Machin ( .NET/ C# MVP ) - 17 Jul 2007 15:57 GMT Hi,
> On Jul 16, 4:26 pm, "Ignacio Machin \( .NET/ C# MVP \)" <machin TA > laceupsolutions.com> wrote: [quoted text clipped - 25 lines] > 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 !!!
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|