By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,203 Members | 1,646 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,203 IT Pros & Developers. It's quick & easy.

Events - Delegates - Inheritance

P: n/a
Tim
There are a set of clients who need to be notified of certain events. I have
used events and delegates (publisher-Subscriber model) for the

notification mechanism. All the clients register with the event publisher
and subscribe for the events that they are interested in. When a certain
event happens, the subscribers are notified about it.
I want the clients to return a value after their callback method is called.
If any of the client returns true, I do not want to invoke the other
subscribers. The order in which the clients are notified is immaterial.

Problem:
How can the clients return a value? According to the MSDN documentation, the
return value is void in the delegate signature. I can change it to int, but
FxCop complains about it.
In Applied Microsoft .Net Framework, Jeffrey Richter talks about using
inheritance to solve this problem - "The derived type might decide not

to have the event forwarded on." Can someone please shed some light on how
to solve the problem?
Dec 14 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Hi,

I think the thing you talk about in the end applies to the case, when a
derived class decides not to call the parent's event handler (like in a
Click event in Windows forms), or something like that.

Multicast delegates always should return void (note the SHOULD in
there). This is because when you invoke them (or an event), and say you
have 10 event handlers registered, which return value would you use? For
this reason, multicast delegates should return void.

However, you should take a look at the GetInvocationList() method of the
MulticastDelegate class (which is what delegates are anyway). This
method will return an array of Delegate objects. You could then use this
array to invoke the delegates manually, and check for a return value, if
you want to continue. This would require only changes in the publisher,
the subscribers would subscribe to the events just as they do now. Of
course you should change the delegates to return a bool value.

When you have the Delegate[] array that is returned, you can go through
that one by one and call the DynamicInvoke() method on them, and check
the return value. Based on that, you can either continue invoking the
delegates or break the loop.

Hope this helps.

-Lenard
PS.
Here is a simple example (although I used static events and methods to
simplyfy):

class Program
{
static event CanContinueDelegate canContinue;

static void Main ( string[] args )
{
canContinue += new CanContinueDelegate ( canContinueEvent );
canContinue += new CanContinueDelegate ( canContinueEvent );
canContinue += new CanContinueDelegate ( canContinueEvent );

Delegate[] delegateList = canContinue.GetInvocationList ();
foreach ( Delegate d in delegateList )
{
if ( (bool)d.DynamicInvoke ( new object[] { "not" } )
== false )
{
break;
}
}

}

static bool canContinueEvent ( string s )
{
Console.WriteLine ( s );
if ( s == "not" )
{
return false;
}
else
{
return true;
}
}
}

Tim wrote:
There are a set of clients who need to be notified of certain events. I have
used events and delegates (publisher-Subscriber model) for the

notification mechanism. All the clients register with the event publisher
and subscribe for the events that they are interested in. When a certain
event happens, the subscribers are notified about it.
I want the clients to return a value after their callback method is called.
If any of the client returns true, I do not want to invoke the other
subscribers. The order in which the clients are notified is immaterial.

Problem:
How can the clients return a value? According to the MSDN documentation, the
return value is void in the delegate signature. I can change it to int, but
FxCop complains about it.
In Applied Microsoft .Net Framework, Jeffrey Richter talks about using
inheritance to solve this problem - "The derived type might decide not

to have the event forwarded on." Can someone please shed some light on how
to solve the problem?

Dec 14 '05 #2

P: n/a
Or just keep it simple :)

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Listeners
{
public interface IListener
{
bool Notify();
}
public class Client : IListener
{
private bool status = false;
private int ID = 0;
public Client(int ID)
{
this.ID = ID;
}
public void TurnOn()
{
this.status = true;
}
public bool Notify()
{
Console.WriteLine("Client "+ID.ToString()+" Notified");
return status;
}
}
class Broadcaster
{
private ArrayList listeners = new ArrayList();
// ASSERT listener is not null
public void Register(IListener listener) {
if (listener == null) { throw new ArgumentException(); }
listeners.Add(listener);
}
public void Broadcast() {
foreach(IListener l in listeners) {
if (l.Notify()) { break; }
}
}
static void Main(string[] args)
{
Client c1 = new Client(1);
Client c2 = new Client(2);
Client c3 = new Client(3);
c2.TurnOn();
Broadcaster b = new Broadcaster();
b.Register(c1);
b.Register(c2);
b.Register(c3);
b.Broadcast();
Console.ReadLine();
}
}
}

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Dec 14 '05 #3

P: n/a
You can do this with events (in their original sense - no hacked return
value) quite easily, by using a different EventArgs class - ideally one
derived from CancelEventArgs, but any custom EventArgs derivative would do,
as long as it has a (settable) property on the class to allow you to
indicate failure.

Fully working example follows; outputs from the first 2 subscribers, but not
the last.

Hope this helps,

Marc

========

public class EventTest {
public static void Main() {
EventTest test = new EventTest();
test.MyEvent += DoSomething;
test.MyEvent += DoSomethingAndComplain;
test.MyEvent += DoSomethingElse;
test.FireTheEvent();
}

static void DoSomething(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoNothing");
}
static void DoSomethingAndComplain(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoSomethingAndComplain");
e.Cancel = true;
}
static void DoSomethingElse(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoSomethingElse");
}

public void FireTheEvent() { // public accessor just to trigger
things
OnMyEvent();
}

public event System.ComponentModel.CancelEventHandler MyEvent;

protected void OnMyEvent() {
if (MyEvent != null) {
System.ComponentModel.CancelEventArgs args = new
System.ComponentModel.CancelEventArgs();
foreach (System.ComponentModel.CancelEventHandler listener
in MyEvent.GetInvocationList()) {
listener(this, args);
if (args.Cancel)
break;
}
}
}

}

"Tim" <Ti*@discussions.microsoft.com> wrote in message
news:71**********************************@microsof t.com...
There are a set of clients who need to be notified of certain events. I
have
used events and delegates (publisher-Subscriber model) for the

notification mechanism. All the clients register with the event publisher
and subscribe for the events that they are interested in. When a certain
event happens, the subscribers are notified about it.
I want the clients to return a value after their callback method is
called.
If any of the client returns true, I do not want to invoke the other
subscribers. The order in which the clients are notified is immaterial.

Problem:
How can the clients return a value? According to the MSDN documentation,
the
return value is void in the delegate signature. I can change it to int,
but
FxCop complains about it.
In Applied Microsoft .Net Framework, Jeffrey Richter talks about using
inheritance to solve this problem - "The derived type might decide not

to have the event forwarded on." Can someone please shed some light on how
to solve the problem?

Dec 14 '05 #4

P: n/a
Tim
Thanks Marc. That's exactly what I was looking for.

"Marc Gravell" wrote:
You can do this with events (in their original sense - no hacked return
value) quite easily, by using a different EventArgs class - ideally one
derived from CancelEventArgs, but any custom EventArgs derivative would do,
as long as it has a (settable) property on the class to allow you to
indicate failure.

Fully working example follows; outputs from the first 2 subscribers, but not
the last.

Hope this helps,

Marc

========

public class EventTest {
public static void Main() {
EventTest test = new EventTest();
test.MyEvent += DoSomething;
test.MyEvent += DoSomethingAndComplain;
test.MyEvent += DoSomethingElse;
test.FireTheEvent();
}

static void DoSomething(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoNothing");
}
static void DoSomethingAndComplain(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoSomethingAndComplain");
e.Cancel = true;
}
static void DoSomethingElse(object sender,
System.ComponentModel.CancelEventArgs e) {
Console.WriteLine("DoSomethingElse");
}

public void FireTheEvent() { // public accessor just to trigger
things
OnMyEvent();
}

public event System.ComponentModel.CancelEventHandler MyEvent;

protected void OnMyEvent() {
if (MyEvent != null) {
System.ComponentModel.CancelEventArgs args = new
System.ComponentModel.CancelEventArgs();
foreach (System.ComponentModel.CancelEventHandler listener
in MyEvent.GetInvocationList()) {
listener(this, args);
if (args.Cancel)
break;
}
}
}

}

"Tim" <Ti*@discussions.microsoft.com> wrote in message
news:71**********************************@microsof t.com...
There are a set of clients who need to be notified of certain events. I
have
used events and delegates (publisher-Subscriber model) for the

notification mechanism. All the clients register with the event publisher
and subscribe for the events that they are interested in. When a certain
event happens, the subscribers are notified about it.
I want the clients to return a value after their callback method is
called.
If any of the client returns true, I do not want to invoke the other
subscribers. The order in which the clients are notified is immaterial.

Problem:
How can the clients return a value? According to the MSDN documentation,
the
return value is void in the delegate signature. I can change it to int,
but
FxCop complains about it.
In Applied Microsoft .Net Framework, Jeffrey Richter talks about using
inheritance to solve this problem - "The derived type might decide not

to have the event forwarded on." Can someone please shed some light on how
to solve the problem?


Dec 14 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.