Using a Delegate to Simulate Invoking Events in Base Class

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

    Using a Delegate to Simulate Invoking Events in Base Class

    I have a base class and derived classes that relate to a set of documents I
    process. e.g. DocBase, DocA, DocB, DocC. The processing of each document is
    handled in teh derived classes, as you might imagine, but the base class has
    properties and methods that are common to all documents.

    The processing of each docuemnt can result in a range of document specific
    errors, which I want to raise as events on the document object, but there
    are some events that are common to all documents, so I would like to have
    those raised in the base class. In fact, I want to raise all events through
    a delegate in the base class so that the object owners don't have to do too
    much work.

    So, I have in mind something like this for the caller:

    Main
    Sub ProcessDocA
    Dim doc As DocBase = New DocA(path)

    doc.Process(Add ressOf DocA_ProcessErr or) <--- Problem here
    End Sub

    Sub ProcessDocB
    Dim doc As DocBase = New DocB(path)

    doc.Process(Add ressOf DocB_ProcessErr or) <--- Problem here
    End Sub

    Sub DocA_ProcessErr or(ByVal sender As Object, ByVal e As
    DocAProcessErro rEventArgs)
    ' Prompt User
    End Sub

    Sub DocB_ProcessErr or(ByVal sender As Object, ByVal e As
    DocBProcessErro rEventArgs)
    ' Prompt User
    End Sub

    My base class looks like this

    Public MustInherit Class DocBase

    Delegate Sub ProcessErrorEve ntHandler(ByVal sender As Object, ByVal
    e As EventArgs)

    Protected ProcessErrorCal lBack As ProcessErrorEve ntHandler

    MustOverride Sub Process(ByVal callback As ProcessErrorEve ntHandler)

    Protected Sub OnProcessError( ByVal e As EventArgs)
    ProcessErrorCal lBack.Invoke(Me , e)
    End Sub

    End Class

    My derived class looks like this

    Public Class DocA

    Inherits DocBase

    Public Overrides Sub Process(ByVal processErrorCal lback As
    ProcessErrorEve ntHandler)
    MyBase.ProcessE rrorCallback = processErrorCal lback

    DoProcessing()

    End Sub

    Private Sub Do Processing()

    ' Trap Error
    MyBase.OnProces sError(New DocAProcessErro rEventArgs("Err or in
    Doc A"))

    End Sub

    End Class


    The problem is where I have arrowed above, becase the compiler doesn't like
    an implicit narrowing conversion from DocA_ProcessErr or() to
    ProcessErrorEve ntHandler.

    I know this all looks very complicated, and perhaps unnecessarily so, but
    can anyone suggest a better, more generic way to do this.

    TIA

    Charles


  • Patrice

    #2
    Re: Using a Delegate to Simulate Invoking Events in Base Class

    Have you tried or do you know about events with the standard OnXXXX
    sub raising the XXXX event ? In your description you are talking
    multiple times about events but you are using delegates in your code
    so I'm not sure if you know about events or if you are trying to avoid
    them for some reason (not sure what is this "too much work" you are
    talking about)...


    --
    Patrice

    Comment

    • Charles Law

      #3
      Re: Using a Delegate to Simulate Invoking Events in Base Class

      Hi Patrice

      Thanks for the reply. I do know about events, but as I understand it events
      in a base class can't be raised by a derived class, so that is why I'm using
      delegates. They also can' te b used as a contract in an interface, which is
      another goal.

      The too much work I'm talking about is work the client of my Doc classes has
      to do. I thought that if they just passed a reference to a call back to
      handle errors then that would be the easiest solution. I also mean that I
      want to impose some sort of contract on the user so that I can use the
      compiler to pickup errors at design time if the classes are not used
      correctly. Also, if I can create an interface in a particular way, it will
      ensure that the rest of the code is written correctly.

      Charles


      "Patrice" <patrice_scribe @hotmail.comwro te in message
      news:4ea6109c-aa5e-4227-9891-d512736b7308@34 g2000hsh.google groups.com...
      Have you tried or do you know about events with the standard OnXXXX
      sub raising the XXXX event ? In your description you are talking
      multiple times about events but you are using delegates in your code
      so I'm not sure if you know about events or if you are trying to avoid
      them for some reason (not sure what is this "too much work" you are
      talking about)...
      >
      >
      --
      Patrice

      Comment

      • Patrice

        #4
        Re: Using a Delegate to Simulate Invoking Events in Base Class

        Try :

        MustInherit Class DocBase
        Event ProcessingError ()
        Protected Overridable Sub OnProcessingErr or()
        Debug.WriteLine ("Here in DocBase.OnProce ssingError")
        RaiseEvent ProcessingError ()
        End Sub
        MustOverride Sub Processing()
        End Sub
        End Class

        Class DocA
        Inherits DocBase
        Sub Processing()
        OnProcessingErr or()
        End Sub
        Sub Test() Handles Me.ProcessingEr ror
        Debug.WriteLine ("Here in DocA.Test that handles
        ProcessingError ")
        End Sub
        End Class

        It will display both messages. Is this what you are looking for ?

        If not the problem in your first code is that you seems to use a
        specific argument type for each of your child class. It should work if
        you replace DocAProcessEven tArgs, DocB... by just EventArgs so that it
        match what you used in the base class.
        --
        Patrice

        Comment

        • Charles Law

          #5
          Re: Using a Delegate to Simulate Invoking Events in Base Class

          Hi Patrice

          I can see what you have done there, and you are right that I am using a
          specific argument type for each of my derived classes.

          I agree that that is the problem, so perhaps I have to find a way to make
          the argument common, even if it is not EventArgs. Currently, each derived
          class returns specific information relating to the document it is
          processing, so I'm not sure how to make the argument common, but I will try.
          It would be nice to find a generic way to do it where the argument types
          were different though.

          Thanks.

          Charles


          "Patrice" <patrice_scribe @hotmail.comwro te in message
          news:b4a9cee4-8dbf-47de-8c39-86fc3c39c3c8@c6 5g2000hsa.googl egroups.com...
          Try :
          >
          MustInherit Class DocBase
          Event ProcessingError ()
          Protected Overridable Sub OnProcessingErr or()
          Debug.WriteLine ("Here in DocBase.OnProce ssingError")
          RaiseEvent ProcessingError ()
          End Sub
          MustOverride Sub Processing()
          End Sub
          End Class
          >
          Class DocA
          Inherits DocBase
          Sub Processing()
          OnProcessingErr or()
          End Sub
          Sub Test() Handles Me.ProcessingEr ror
          Debug.WriteLine ("Here in DocA.Test that handles
          ProcessingError ")
          End Sub
          End Class
          >
          It will display both messages. Is this what you are looking for ?
          >
          If not the problem in your first code is that you seems to use a
          specific argument type for each of your child class. It should work if
          you replace DocAProcessEven tArgs, DocB... by just EventArgs so that it
          match what you used in the base class.
          --
          Patrice
          >

          Comment

          • =?Utf-8?B?SkI=?=

            #6
            Re: Using a Delegate to Simulate Invoking Events in Base Class

            refering to the Foo event in Bill McCarthy's reply, there are several ways of
            defining different event data for each derived class. One way is to define a
            base class event args
            Friend Class FooBaseEventArg s
            Inherits System.EventArg s

            Friend New( .. )

            .. you can include an e.g. typeID so the comsumer can determine
            .. the actual eventargs type,
            .. Or use typeof or some other logic

            .. properties ..
            end class

            then
            Friend Class Derived1_FooEve ntArgs
            Inherits FooBaseEventArg s

            ...
            End Class

            and so on...

            In the base class,
            Protected Sub OnFoo(ev as FooBaseEventArg s)
            ( you don't need the Overriable if you are only going to invoke the event)

            Then in the derived class,
            Dim eArgs as New Derived1_FooEve ntArgs(..)
            OnFooEvent(eArg s)

            There are other schemes for accomplishing the same thing. It is then up to
            the comsumer of the event to sort out the desired data from the event data
            --
            JB


            "Bill McCarthy" wrote:
            Hi Charles,
            >
            "Charles Law" <blank@nowhere. comwrote in message
            news:uBZcJLPIJH A.1556@TK2MSFTN GP03.phx.gbl...
            Hi Patrice

            Thanks for the reply. I do know about events, but as I understand it
            events in a base class can't be raised by a derived class, so that is why
            I'm using delegates.
            >
            The Usual Pattern there is to have:
            >
            Class BaseClass
            >
            Event Foo As EventHandler
            >
            Protected Overridable Sub OnFoo(ev as eventargs)
            RasieEvent Foo(Me,ev)
            End sub
            End CLass
            >
            Class Derived : Inherits BaseClass
            >
            Sub Dosomething
            OnFoo(eventargs .empty)
            End sub
            End Class
            >
            >
            They also can' te b used as a contract in an interface, which is another
            goal.
            >
            >
            Yes they can.
            >
            >
            >

            Comment

            • Charles Law

              #7
              Re: Using a Delegate to Simulate Invoking Events in Base Class

              Hi JB

              My news reader isn't showing Bill's reply, so I have only just seen it in
              your reply below.

              I started down this route, and then decided that I didn't want the consumer
              to have to cast the eventargs parameter received to the specific derived
              eventargs type for the event. I wanted them to receive the correctly typed
              parameter for the event raised by the derived class.

              Charles


              "JB" <JB@discussions .microsoft.comw rote in message
              news:DDAEC737-365D-445B-9A87-6976229781BC@mi crosoft.com...
              refering to the Foo event in Bill McCarthy's reply, there are several ways
              of
              defining different event data for each derived class. One way is to
              define a
              base class event args
              Friend Class FooBaseEventArg s
              Inherits System.EventArg s
              >
              Friend New( .. )
              >
              .. you can include an e.g. typeID so the comsumer can determine
              .. the actual eventargs type,
              .. Or use typeof or some other logic
              >
              .. properties ..
              end class
              >
              then
              Friend Class Derived1_FooEve ntArgs
              Inherits FooBaseEventArg s
              >
              ...
              End Class
              >
              and so on...
              >
              In the base class,
              Protected Sub OnFoo(ev as FooBaseEventArg s)
              ( you don't need the Overriable if you are only going to invoke the
              event)
              >
              Then in the derived class,
              Dim eArgs as New Derived1_FooEve ntArgs(..)
              OnFooEvent(eArg s)
              >
              There are other schemes for accomplishing the same thing. It is then up
              to
              the comsumer of the event to sort out the desired data from the event data
              --
              JB
              >
              >
              "Bill McCarthy" wrote:
              >
              >Hi Charles,
              >>
              >"Charles Law" <blank@nowhere. comwrote in message
              >news:uBZcJLPIJ HA.1556@TK2MSFT NGP03.phx.gbl.. .
              Hi Patrice
              >
              Thanks for the reply. I do know about events, but as I understand it
              events in a base class can't be raised by a derived class, so that is
              why
              I'm using delegates.
              >>
              >The Usual Pattern there is to have:
              >>
              >Class BaseClass
              >>
              > Event Foo As EventHandler
              >>
              > Protected Overridable Sub OnFoo(ev as eventargs)
              > RasieEvent Foo(Me,ev)
              > End sub
              >End CLass
              >>
              >Class Derived : Inherits BaseClass
              >>
              > Sub Dosomething
              > OnFoo(eventargs .empty)
              > End sub
              >End Class
              >>
              >>
              They also can' te b used as a contract in an interface, which is
              another
              goal.
              >
              >>
              >>
              >Yes they can.
              >>
              >>
              >>

              Comment

              Working...