473,406 Members | 2,954 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Delegate et al

Hi,

I am thinking about the delegate mechanism and try to understand it. I
am coming from
C++ and know about callbacks or member callbacks.

In C++ I have this typedef for every class that implements member
callbacks:
typedef bool (__cdecl IEventHandler::*lbEvHandler)(IUnknown* uk);

Each class, that implements such methods, would register these by this
method call:
IDispatcher* disp = getDispatcher();
disp->addEventHandlerFn(this, (lbEvHandler) &MyClass::MyFoo, "MyFoo");

Thus, calling such a method is done by:
IDispatcher* disp = getDispatcher();
disp->dispatch("MyFoo", myParam, &result);

So, my dispatcher knows of all my registered functions and can invoke
it by name.
The second parameter is the functions needed data and the last is for
error handling.

This way I can register a buttons click event to any instance,
supporting that event.

Using delegates, I don't know, how to do similar stuff. Especially, the
AddressOf
mechanism seems to be only for the method, but how about multible
instances of the
same class ?

See the 'this' parameter for the instance, providing that function.

Did AddressOf returns an implicit value for 'this' ?

I need this information, bacause in C++ I store both, object instance
pointer and member
pointer to the function.

Any help ?

Thanks, Lothar

Jul 12 '06 #1
3 1373
>Using delegates, I don't know, how to do similar stuff. Especially, the
AddressOf
mechanism seems to be only for the method, but how about multible
instances of the
same class ?

See the 'this' parameter for the instance, providing that function.

Did AddressOf returns an implicit value for 'this' ?
The default is 'this' (or rather Me in VB) but you can use the syntax

AddressOf someOtherInstance.HandlerMethod

for other objects.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Jul 12 '06 #2
Lothar (!!) wrote:
(inline)
Hi,

I am thinking about the delegate mechanism and try to understand it. I
am coming from
C++ and know about callbacks or member callbacks.

In C++ I have this typedef for every class that implements member
callbacks:
typedef bool (__cdecl IEventHandler::*lbEvHandler)(IUnknown* uk);
In VB it would be:

Delegate Function lbEvHandler(Uk As IUnknown) As Boolean

Notice that only the method signature is necessary, not the base class.
In fact any method with this same signature (even shared (static)
methods) regardless of the class where it's implemented is a suitable
lbEventHandler delegate.
Each class, that implements such methods, would register these by this
method call:
IDispatcher* disp = getDispatcher();
disp->addEventHandlerFn(this, (lbEvHandler) &MyClass::MyFoo, "MyFoo");

Thus, calling such a method is done by:
IDispatcher* disp = getDispatcher();
disp->dispatch("MyFoo", myParam, &result);

So, my dispatcher knows of all my registered functions and can invoke
it by name.
The second parameter is the functions needed data and the last is for
error handling.
Delegates have single and multi dispatch built in. When you add a
handler to a delegate, whenever it's Invoke method is called, your
handler will be called also, automagically.

One possible scenario of using delegates is as simple function
pointers. For historical reasons, you pass the address of a method to a
delegate using the AddressOf operator. You execute the actual
'delegated' method by calling the delegate's Invoke method.

Function OnLblEvent(U As IUnknown) AS Boolean
'...
End Function
'...
Dim S As New lbEvHandler(AddressOf OnLblEvent)
'Which is similar to:
Dim R As lbEvHandler = AddressOf OnLblEvent
Dim I As IUnknwon
Dim Result As Boolean = S.Invoke(I)

As you can see, the Invoke method of a given delegate will have the
same signature of the delegate's declaration.
This way I can register a buttons click event to any instance,
supporting that event.
As for events, there are various approaches to add handlers to them.
Suppose you have a Button (OkButton) that raises the event Sub
Click(Sender As Object). One way of adding handlers to this event would
be:

'the following is needed when you use
'the inline Handles clause to automatically
'declare handlers:
Private WithEvents OkButton

Sub OnButtonClick(Sender As Object) _
Handles OkButton.Click
'...
End Sub

Or you could do it dinamically:

AddHandler OkButton.Click, AddressOf OnButtonClick

Or still:

Dim H As ClickEventHandler = AddressOf OnButtonClick
'...
AddHandler OkButton.Click, H

You can add as many handlers as you want to a given event:

AddHandler OkButton.Click AddressOf OnButtonClick
AddHandler OkButton.Click AddressOf ClickHandler
Addhandler OkButton.Click AddressOf AnotherClickHandler
'...

Likewise, you can use a given handler to listen to any number of events
from whatever sources:

For Each C As Control In Controls
If TypeOf C is Button Then
AddHandler C.Click, AddressOf GlobalClickHandler
End If
Next
Using delegates, I don't know, how to do similar stuff. Especially, the
AddressOf
mechanism seems to be only for the method, but how about multible
instances of the
same class ?
I'm not sure if I understand the question. The AddressOf returns a
specific instance of a method, be it a shared (static) or an non-shared
method of a class. I mean, it represents an actual method from a specic
object.

Now, suppose you have many instaces of a given class (Listener), and
all of then wanted to 'listen' to events of a given object (Source),
say, the good old Click event.

To make things clearer, suppose you have a method in some other class
(Dispatcher) which gets a list of listeners that must be attached to
the source event:

Class Listener
Public Sub Click(Sender As Object): end Sub
End Class

Class EventSource
Public Event Click(Sender As Object)
'...
Sub DoIt
'...
RaiseEvent Click(Me) '<-- Keep an eye on here
End If
End Class

Class Dispatcher
Dim mEventSource As New EventSource

Sub AddListeners(List As IEnumerable(Of Listener))
For Each L As Listener In List
AddHandler mEventSource.Click, AddressOf L.Click
Next
End Sub

Sub MeanwhileOnAnotherPlanet
mEventSource.DoIt
End Sub

End Class

When the Source class executes the RaiseEvent action inside the DoIt
method, all event handlers attached to the Click event will be executed
in the order in wich they were registered.
See the 'this' parameter for the instance, providing that function.

Did AddressOf returns an implicit value for 'this' ?

I need this information, bacause in C++ I store both, object instance
pointer and member
pointer to the function.
As you've seen, the AddressOf returns both the Object and method
addresses (the Object will be null for shared methods, I guess), but it
does so implicitly

HTH.

Regards,

Branco.

Jul 12 '06 #3

Branco Medeiros wrote:
Lothar (!!) wrote:
(inline)
Hi,

I am thinking about the delegate mechanism and try to understand it. I
am coming from
C++ and know about callbacks or member callbacks.

In C++ I have this typedef for every class that implements member
callbacks:
typedef bool (__cdecl IEventHandler::*lbEvHandler)(IUnknown* uk);

In VB it would be:

Delegate Function lbEvHandler(Uk As IUnknown) As Boolean

Notice that only the method signature is necessary, not the base class.
In fact any method with this same signature (even shared (static)
methods) regardless of the class where it's implemented is a suitable
lbEventHandler delegate.
Each class, that implements such methods, would register these by this
method call:
IDispatcher* disp = getDispatcher();
disp->addEventHandlerFn(this, (lbEvHandler) &MyClass::MyFoo, "MyFoo");

Thus, calling such a method is done by:
IDispatcher* disp = getDispatcher();
disp->dispatch("MyFoo", myParam, &result);

So, my dispatcher knows of all my registered functions and can invoke
it by name.
The second parameter is the functions needed data and the last is for
error handling.

Delegates have single and multi dispatch built in. When you add a
handler to a delegate, whenever it's Invoke method is called, your
handler will be called also, automagically.

One possible scenario of using delegates is as simple function
pointers. For historical reasons, you pass the address of a method to a
delegate using the AddressOf operator. You execute the actual
'delegated' method by calling the delegate's Invoke method.

Function OnLblEvent(U As IUnknown) AS Boolean
'...
End Function
'...
Dim S As New lbEvHandler(AddressOf OnLblEvent)
'Which is similar to:
Dim R As lbEvHandler = AddressOf OnLblEvent
Dim I As IUnknwon
Dim Result As Boolean = S.Invoke(I)
You only register the function to the handler. (Line 1)

I need to dispatch an event to one S[eventname] in in a list of
multiple S'.
A mapping of ID/EventName to S must be applied (dispatch).

I have the following requirements:

A GUI client get's information, what menu and what entries it has to
build.
This information is passed by strings, because the GUI cannot call
function pointers.
To be prcicely, it is WinDev and our middle layer is .NET Assemblies.

' A plugin's code

Function OnMenuOpenFileEvent(U As IUnknown) AS Boolean
'...
End Function

Function OnMenuNewFileEvent(U As IUnknown) AS Boolean
'...
End Function

Function OnMenuSaveFileEvent(U As IUnknown) AS Boolean
'...
End Function

Sub Init()

Dim evM as EventManager = GetGlobalEventManager() ' Singleton
Dim appM as ApplicationManager = GetGlobalApplicationManager() '
Singleton
Dim disp as Dispatcher = GetGlobalDispatcher() ' Singleton
Dim evID as Integer

evM.registerHandler("OnMenuOpenFileEvent", evID) ' evID parameter
gets the id (ByRef)
disp.registerHandlerMethod("OnMenuOpenFileEvent", AddressOf
OnMenuOpenFileEvent)
or
disp.registerHandlerMethod(evID, AddressOf OnMenuOpenFileEvent)
to avoid multiple eventID lookups (by invoking
EventManager.resolveName("OnMenuOpenFileEvent") inside of the
dispatcher).

evM.registerHandler("OnMenuNewFileEvent", evID) ' evID parameter
gets the id (ByRef)
disp.registerHandlerMethod("OnMenuNewFileEvent", AddressOf
OnMenuNewFileEvent)

evM.registerHandler("OnMenuSaveFileEvent", evID) ' evID parameter
gets the id (ByRef)
disp.registerHandlerMethod("OnMenuSaveFileEvent", AddressOf
OnMenuSaveFileEvent)

appM.AddMenu("&File")
appM.AddMenuEntry("&File", "&New", "OnMenuNewFileEvent")
appM.AddMenuEntry("&File", "&Open", "OnMenuOpenFileEvent")
appM.AddMenuEntry("&File", "&Save", "OnMenuSaveFileEvent")
End Sub

The handling of information passing (AddMenu*) to the GUI is not shown
here.
Maybe it will be message passing.

As you see, the GUI did not directly expose it's menu Click's, because
it is not VB,
nor any .NET language (but can use .NET).

So I must use identifers like strings, or to fasten it, their
registered ID's.

The GUI could use .NET assemblies, thus it will have access to the
dispatcher et al.
Given, the GUI controls are proper set up to route its events to a
WinDev specific
handler (catch all), it is capable to build a bunch of information, the
handler needs and
pass it with the following code to the handler in behind:

myParameter is IParameter object dynamic // WinDev code !
myParameter = getParameterInstance() // WinDev code !

myResult is IParameter object dynamic // WinDev code !
myResult = getParameterInstance() // WinDev code !

// Fill the parameter with the required data (application specific)
// What to fill was given to the GUI with the handler to be 'called',
eg
// 'Fill with control 'Name', 'SureName', 'Age' ...
// This is very generic and highly dynamic.

MyParameter.addParameter('Name', {'Name'} .. Value) // WinDev code !

disp.dispatch(event.id, myParameter, myResult) // WinDev code !
AddHandler OkButton.Click AddressOf OnButtonClick
AddHandler OkButton.Click AddressOf ClickHandler
Addhandler OkButton.Click AddressOf AnotherClickHandler
Direct access to the control is impossible. Control is in GUI and
handler in plugin.
'...

Likewise, you can use a given handler to listen to any number of events
from whatever sources:

For Each C As Control In Controls
If TypeOf C is Button Then
AddHandler C.Click, AddressOf GlobalClickHandler
End If
Next
Using delegates, I don't know, how to do similar stuff. Especially, the
AddressOf
mechanism seems to be only for the method, but how about multible
instances of the
same class ?

I'm not sure if I understand the question. The AddressOf returns a
specific instance of a method, be it a shared (static) or an non-shared
method of a class. I mean, it represents an actual method from a specic
object.
One navigation toolbar with buttons for 'First', 'Previous', 'Next' and
'Last' and multiple
data windows with their handlers. The GUI part of the data window is
built up upon
information from the middle layer. The handlers are specific to the
'bussiness' object.

On C++ I have solved this, by prepending the address od 'this' as
string to the handler
name. This is not yet one button to many handlers (one per active
window), but it should
be. The dispatcher may not find the eventhandler by searching for
'OnNext', but the GUI
may provide information, such as window name. Thus this could be
prepended and also
the bussiness logic, that requests for a data window may provide a
window name, if
multible windows are needed.

Maybe the bussiness logic registers generic handlers for 'OnFirst', ...
and do
subdispatching like this:

if (!disp.dispatch("OnFirst", ...)) // If a generic handler is
registered
// Fallback to new approach
disp.dispatch("current window's name, that who lost the focus to
the toolbar" & "OnFirst", ...)

I think the Toolbar for data navigation is a good example.

/---Handler for DataWindow1
Toolbar ---<
\---Handler for DataWindow2

Actually, this would by a candidat of implementation for my C++
project, but also for
this one.

Thus only the real listener of such events gets informed.
And no event handler has to be re-registered at window focus issues.
>
Now, suppose you have many instaces of a given class (Listener), and
all of then wanted to 'listen' to events of a given object (Source),
say, the good old Click event.
Doing this with the dispatcher, I must implement a registerListener
method.
I think, that is not required yet.
>
To make things clearer, suppose you have a method in some other class
(Dispatcher) which gets a list of listeners that must be attached to
the source event:

Class Listener
Public Sub Click(Sender As Object): end Sub
End Class

Class EventSource
Public Event Click(Sender As Object)
'...
Sub DoIt
'...
RaiseEvent Click(Me) '<-- Keep an eye on here
End If
End Class

Class Dispatcher
Dim mEventSource As New EventSource

Sub AddListeners(List As IEnumerable(Of Listener))
For Each L As Listener In List
AddHandler mEventSource.Click, AddressOf L.Click
Next
End Sub

Sub MeanwhileOnAnotherPlanet
mEventSource.DoIt
End Sub

End Class
Maybe I use this sample for the listener or observer pattern.
When the Source class executes the RaiseEvent action inside the DoIt
method, all event handlers attached to the Click event will be executed
in the order in wich they were registered.
See the 'this' parameter for the instance, providing that function.

Did AddressOf returns an implicit value for 'this' ?

I need this information, bacause in C++ I store both, object instance
pointer and member
pointer to the function.

As you've seen, the AddressOf returns both the Object and method
addresses (the Object will be null for shared methods, I guess), but it
does so implicitly
The main issues may be, that I have no direct access from the event
source to the
event target. Using a dispatching mechanism with unique ID's per
application instance,
it would be possible to route an event to it's target.

It's a little more than dynamically creating delegates :-(

It has helped :-)

Regards

Lothar

Jul 13 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Minh Khoa | last post by:
Please give me more information about delegate and its usage? Why do i use it and when?
4
by: ^MisterJingo^ | last post by:
Hi all, I've been trying to get my head around delegates. The book i'm using had a single example, not much explaination, and didn't show how to set up a delegate and pass variables in and out...
3
by: Jeff S | last post by:
Please consider this sample code: It registers a delegate with an event. p1.FirstNameChanged += new Person.NameChanged(p1_FirstNameChanged); Now the following code removes the delegate:...
7
by: Ant | last post by:
Hello, Very simple question but one I need clarified. Which part of the statement below is considered the 'delegate'? Is it the 'new System.EventHandler' or the btnAccept_Click? or is it...
6
by: David Veeneman | last post by:
I have several events that pass a value in their event args. One event passes an int, another a string, another a DateTime, and so on. Rather than creating a separate set of event args for each...
1
by: Quimbly | last post by:
I'm having some problems comparing delegates. In all sample projects I create, I can't get the problem to occur, but there is definitely a problem with my production code. I can't give all the...
11
by: matsi.inc | last post by:
I am looking to make something like a delegate that i can use in my projects but am having a hard time getting started. The behavior I am most interested in is how a delegate changes it's Invoke...
6
by: damiensawyer | last post by:
Hi, Can someone please explain to me something about delegates? My understanding is as follows. A delegate is basically an object that can hold a reference to a "method" somewhere. That is,...
26
by: raylopez99 | last post by:
Here is a good example that shows generic delegate types. Read this through and you'll have an excellent understanding of how to use these types. You might say that the combination of the generic...
10
by: vcquestions | last post by:
Hi. Is there way to have a function pointer to a delegate in c++/cli that would allow me to pass delegates with the same signatures as parameters to a method? I'm working with managed code. ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.