Hi everyone :) this is my first question on stackoverflow :)
in Delphi XE2 RTTI we have the TRttiMethod class and it has the CreateImplementation() function, which allows you to dynamically create a procedure or function with the same signature and anonymous method as its body.
using TRttiContext.getMethods() / getMethod() , we can get a set of class methods - a collection of TRttiMethod.
In the documentation
( http://docwiki.embarcadero.com/VCL/en/RTTI.TRttiMethod ) you do not need to directly create TRTTiMethod and use getMethods () to get your instances.
therefore, if we have an instance of TRTTIMethod , we can dynamically create a method with the same signature and call it later.
the question is .. for example, we have TNotifyEvent ... TRttiContext.getType(typeinfo(TNotifyEvent)) returns an instance object TRttiType that has typekind = tkMethod . we know that the signature TNotifyEvent is the procedure (sender: TObject) of the object;
Is it possible to get TRTTIMethod for this? Do I want to dynamically create an eventHandler for an event using TRttiMethod.CreateImplementation() or can there be another way to dynamically create a method implementation?
PS: the idea is to create something like an Event Chain. At compile time, we donβt know the type of event / signature, so we can use generics like TEvenChain <TNotifyEvent> for this. The chain has a collection of registered event handlers, therefore, since we do not know the type of handler at compile time, we need to dynamically create it, and this handler receives its parameters and calls the registered handler with them.
update: here is some code (the idea is to create chains of event handlers):
procedure TMainForm.FormCreate(Sender: TObject); begin FEventChain := TNotifyChain.Create(); FEventChain.AddHandler(event1); FEventChain.AddHandler(event2); TestButton.OnClick := FEventChain.EventHandler; end;
Event1 and event2 are methods (sender : TObject) form; this is not a general example (T in this case NotifyEvent / TChain <TNotifyEvent>) TEventChain.EventHandler also TNotifyEvent
TNotifyChain is
TNotifyChain = class(TObject) strict private FEvent : TNotifyEvent; FItems : TList<TNotifyEvent>; FCtx : TRttiContext; public procedure TestNotifyHandler(sender : TObject); virtual; abstract; constructor Create(); procedure AddHandler(eh : TNotifyEvent); property EventHandler : TNotifyEvent read FEvent; end;
EventHandler property maps to the FEvent variable. And FEvent not assigned, as we assume that the type of event / handler is unknown.
therefore, in the constructor, we create a virtual method with the TNotifyEvent signature and assign its FEvent code:
constructor TNotifyChain.Create(); var st: TRttiType; //et : TRttiMethodType; Callback : TMethodImplementationCallback; rttiMethod : TRttiMethod; m : TMethod; mi : TMethodImplementation; begin inherited; FItems := TList<TNotifyEvent>.Create(); FCtx := TRttiContext.Create(); //et := FCtx.GetType(typeinfo(TNotifyEvent)) as TRttiMethodType; st := FCtx.GetType(self.ClassType); rttiMethod := st.GetMethod('TestNotifyHandler'); Callback := procedure(UserData: Pointer; const Args: TArray<TValue>; out Result: TValue) var i : integer; e : TMethod; begin for i := 0 to FItems.Count - 1 do begin e := TMethod(Fitems[i]); result := Invoke(e.Code, args, rttiMethod.CallingConvention, nil); end; end; mi := rttiMethod.CreateImplementation(self, Callback); m.data := self; m.Code := mi.CodeAddress; FEvent := TNotifyEvent(m); end;
here I am using the TestNotifyHandler method to create an actual handler with the same signature using TRttiMethod.CreateImplementation()
I suppose there is a way to create an implementation of an event handler at runtime using TRttiMethodType from TNotifyEvent , because it has information about the type / count parameters and the conditional call of the actual event (in general).