1. How can I dynamically store events – they can not be added to a
Tlist.
2. How can I pass events as arguments, again generically – I would like
my Tnotifier to have a function such as
procedure TNotifier.RegisterEvent (aDelphiEvent :
IWhishIKnewWhatTypeToPutHere);
Since events are types, and not objects, I can’t use an abstract super
class approach (i.e. TObject) that will allow me to pass events as
arguments or to assign events to variables (and typecast them before
the actual usage).
Any ideas about how to approach this?
Daniel Oppenheim
mu...@watson.ibm.com
..........
>1. How can I dynamically store events – they can not be added to a
>Tlist.
You can store the adresses of dymacilally created tmethod structures.
>2. How can I pass events as arguments, again generically – I would like
>my Tnotifier to have a function such as
> procedure TNotifier.RegisterEvent (aDelphiEvent :
>IWhishIKnewWhatTypeToPutHere);
TNotifier.RegisterEvent (aDelphiEvent : tMethod);
Roman
KRE...@mbox.cesnet.cz
(please remove STOPSPAM. in header]
type pNotifyEvent = ^tnotifyevent;
var
List : TList;
n1 : pNotifyEvent;
procedure TForm1.FormCreate(Sender: TObject);
var
n:integer;
begin
List := tlist.create;
try
getmem(n1,sizeof(tnotifyevent));
n1^ := button1Click;
list.add(n1);
getmem(n1,sizeof(tnotifyevent));
n1^ := form2.button1click;
list.add(n1);
getmem(n1,sizeof(tnotifyevent));
n1^ := form3.button1click;
list.add(n1);
for n := 0 to 2 do begin
n1 := list[n];
n1^(self);
end;
for n := 2 downto 0 do begin
freemem(list[n],sizeof(TNotifyEvent));
list.delete(n);
end;
finally
list.free;
end;
end;
How you'd keep watch on the type of function you'd add to the list may
require a little more thought.
Kind Regards
Claire, c...@nospam.HallworthHome.demon.co.uk
1. Each TNotifier instance will only hold method pointers of one type.
In this case you could derive a new TNotifier descendent from a common base
class for each new method type you need to handle. The internal list of the
notifier class would store the method pointers themselves, which is generic
and can be implemented in the base class. If you use a TList you could
simply use two slots of the TList per method, one for the code part, one
for the object address. This avoids usage of a wrapper class just to store
the method pointers.
Function TMethodList.AddMethod( aMethod: TMethod ): Integer;
Begin
Result := Add( aMethod.Code ) div 2;
Add( aMethod.Data );
End;
This way the code pointers would always be stored at even indices, the
object reference at odd indices (from the view of TList, for the
TMethodLIst the indices would go from 0 to (count div 2)-1). To get methods
back you would have a
Function TMethodLIst.GetMethod( index: Integer ): TMethod;
Begin
Result.Code := Items[ index * 2 ];
Result.Data := Items[ index * 2 + 1];
End;
A MethodCount property could be implemented to hide the fact that each
entry consumes 8 bytes.
This takes care of storing the method references, calling the methods would
be via a method of the appropriate TMethodList descendent. You cannot
easily use a virtual method and polymorphism here (but it would be
possible, in principle, using an array of const as parameter passing
mechanism). The code that uses the TMethodList instance would need to now
the actual class of the instance, to be able to call this method and
provide the correct parameters to pass to each method. E.g.
Type
TNotificationList = Class( TMethodList )
public
Procedure FireEvents( aSender: TObject );
end;
Procedure TNotificationList.FireEvents( aSender: TObject );
Var
i: Integer;
m: TMethod;
Begin
For i:= 0 To (count div 2) - 1 Do Begin
m:= GetMethod( i );
If Assigned(m) Then
TNotifyEvent(m)(aSender);
End;
End;
2. Any TNotifier instance has to handle different method types.
In this case you need wrapper objects for each method pointer type, the
wrapper class is the one that knows the method type and stores the
parameters for the method call. The base class would have a virtual
FireEvent method that each descendent overrides to handle a specific method
type. A client would create an instance of the proper class for its event
and register this event with the notifier by adding the object to the
notifiers list (which can now be a simple TList). It could set default
parameters for the method call, the parameters would be stored in fields of
the object. To fire the events in the list the notifier would just call the
FireEvent method of each object it stores. The code triggering the events
would have the option of looking through the list of event objects and set
parameters before the call (it would have to know which event object types
to look for). The event objects could have ParambyName and HasParam virtual
methods that would allow an interesting party to inquire about the
existence of a parameter by name.
Peter Below (TeamB) 10011...@compuserve.com)