|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Delegate et alI 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 >Using delegates, I don't know, how to do similar stuff. Especially, the The default is 'this' (or rather Me in VB) but you can use the syntax>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' ? 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. Lothar (!!) wrote:
(inline) > Hi, In VB it would be:> > 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); 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 Delegates have single and multi dispatch built in. When you add a> 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. 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, As for events, there are various approaches to add handlers to them.> supporting that event. 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 I'm not sure if I understand the question. The AddressOf returns a> AddressOf > mechanism seems to be only for the method, but how about multible > instances of the > same class ? 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. As you've seen, the AddressOf returns both the Object and method> > 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. addresses (the Object will be null for shared methods, I guess), but it does so implicitly HTH. Regards, Branco. Branco Medeiros wrote:
Show quoteHide quote > Lothar (!!) wrote: You only register the function to the handler. (Line 1)> (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) > 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 Direct access to the control is impossible. Control is in GUI and> AddHandler OkButton.Click AddressOf ClickHandler > Addhandler OkButton.Click AddressOf AnotherClickHandler handler in plugin. Show quoteHide quote > '... One navigation toolbar with buttons for 'First', 'Previous', 'Next' and> > 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. '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. > Doing this with the dispatcher, I must implement a registerListener> 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. method. I think, that is not required yet. Show quoteHide quote > Maybe I use this sample for the listener or observer pattern.> 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 > Show quoteHide quote > When the Source class executes the RaiseEvent action inside the DoIt The main issues may be, that I have no direct access from the event> 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 > 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
Validating textbox w/ Cancel button
sql server 2005 tools configuration starts when I build a distribution project (VB 2005) for next problem Outlook Add In suddenly stops loading Referring form objects in VB 2005. TypeForwardedToApp attribute. Replacement for Inet Control text justification in excel Determine projects in solution within VS2005 macro Checked List Box Help |
|||||||||||||||||||||||