Events - Delegates - Inheritance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tim

    #1

    Events - Delegates - Inheritance

    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?
  • Lenard Gunda

    #2
    Re: Events - Delegates - Inheritance

    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 GetInvocationLi st() method of the
    MulticastDelega te 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 CanContinueDele gate canContinue;

    static void Main ( string[] args )
    {
    canContinue += new CanContinueDele gate ( canContinueEven t );
    canContinue += new CanContinueDele gate ( canContinueEven t );
    canContinue += new CanContinueDele gate ( canContinueEven t );

    Delegate[] delegateList = canContinue.Get InvocationList ();
    foreach ( Delegate d in delegateList )
    {
    if ( (bool)d.Dynamic Invoke ( new object[] { "not" } )
    == false )
    {
    break;
    }
    }

    }

    static bool canContinueEven t ( string s )
    {
    Console.WriteLi ne ( s );
    if ( s == "not" )
    {
    return false;
    }
    else
    {
    return true;
    }
    }
    }



    Tim wrote:[color=blue]
    > 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?[/color]

    Comment

    • Jeff Louie

      #3
      Re: Events - Delegates - Inheritance

      Or just keep it simple :)

      using System;
      using System.Collecti ons.Generic;
      using System.Text;
      using System.Collecti ons;

      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.WriteLi ne("Client "+ID.ToString() +" Notified");
      return status;
      }
      }
      class Broadcaster
      {
      private ArrayList listeners = new ArrayList();
      // ASSERT listener is not null
      public void Register(IListe ner listener) {
      if (listener == null) { throw new ArgumentExcepti on(); }
      listeners.Add(l istener);
      }
      public void Broadcast() {
      foreach(IListen er 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.ReadLin e();
      }
      }
      }

      Regards,
      Jeff

      *** Sent via Developersdex http://www.developersdex.com ***

      Comment

      • Marc Gravell

        #4
        Re: Events - Delegates - Inheritance

        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 += DoSomethingAndC omplain;
        test.MyEvent += DoSomethingElse ;
        test.FireTheEve nt();
        }

        static void DoSomething(obj ect sender,
        System.Componen tModel.CancelEv entArgs e) {
        Console.WriteLi ne("DoNothing") ;
        }
        static void DoSomethingAndC omplain(object sender,
        System.Componen tModel.CancelEv entArgs e) {
        Console.WriteLi ne("DoSomething AndComplain");
        e.Cancel = true;
        }
        static void DoSomethingElse (object sender,
        System.Componen tModel.CancelEv entArgs e) {
        Console.WriteLi ne("DoSomething Else");
        }

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

        public event System.Componen tModel.CancelEv entHandler MyEvent;

        protected void OnMyEvent() {
        if (MyEvent != null) {
        System.Componen tModel.CancelEv entArgs args = new
        System.Componen tModel.CancelEv entArgs();
        foreach (System.Compone ntModel.CancelE ventHandler listener
        in MyEvent.GetInvo cationList()) {
        listener(this, args);
        if (args.Cancel)
        break;
        }
        }
        }

        }

        "Tim" <Tim@discussion s.microsoft.com > wrote in message
        news:71ECFAC2-DBF1-430D-B81A-F998E018B11F@mi crosoft.com...[color=blue]
        > 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?[/color]


        Comment

        • Tim

          #5
          Re: Events - Delegates - Inheritance

          Thanks Marc. That's exactly what I was looking for.

          "Marc Gravell" wrote:
          [color=blue]
          > 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 += DoSomethingAndC omplain;
          > test.MyEvent += DoSomethingElse ;
          > test.FireTheEve nt();
          > }
          >
          > static void DoSomething(obj ect sender,
          > System.Componen tModel.CancelEv entArgs e) {
          > Console.WriteLi ne("DoNothing") ;
          > }
          > static void DoSomethingAndC omplain(object sender,
          > System.Componen tModel.CancelEv entArgs e) {
          > Console.WriteLi ne("DoSomething AndComplain");
          > e.Cancel = true;
          > }
          > static void DoSomethingElse (object sender,
          > System.Componen tModel.CancelEv entArgs e) {
          > Console.WriteLi ne("DoSomething Else");
          > }
          >
          > public void FireTheEvent() { // public accessor just to trigger
          > things
          > OnMyEvent();
          > }
          >
          > public event System.Componen tModel.CancelEv entHandler MyEvent;
          >
          > protected void OnMyEvent() {
          > if (MyEvent != null) {
          > System.Componen tModel.CancelEv entArgs args = new
          > System.Componen tModel.CancelEv entArgs();
          > foreach (System.Compone ntModel.CancelE ventHandler listener
          > in MyEvent.GetInvo cationList()) {
          > listener(this, args);
          > if (args.Cancel)
          > break;
          > }
          > }
          > }
          >
          > }
          >
          > "Tim" <Tim@discussion s.microsoft.com > wrote in message
          > news:71ECFAC2-DBF1-430D-B81A-F998E018B11F@mi crosoft.com...[color=green]
          > > 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?[/color]
          >
          >
          >[/color]

          Comment

          Working...