Ciao a tutti :) E 'la mia prima domanda a StackOverflow :)È possibile creare un'istanza TRttiMethod per TRttiType con TypeKind = tkMethod?
in Delphi XE2 RTTI abbiamo classe TRttiMethod ed ha la funzione CreateImplementation()
scomparsa che permette di creare dinamicamente procedura o funzione con la stessa firma e un metodo anonimo come il suo corpo.
utilizzando TRttiContext.getMethods()
/getMethod()
possiamo ottenere la raccolta di metodi di classe - raccolta di TRttiMethod.
documentazione dice (http://docwiki.embarcadero.com/VCL/en/RTTI.TRttiMethod) non creare TRTTiMethod direttamente e utilizzare getMethods() per ottenere le sue istanze.
quindi, se abbiamo istanza TRTTIMethod
, possiamo creare dinamicamente il metodo con la stessa firma e richiamarlo in seguito.
la domanda è .. per esempio, abbiamo TNotifyEvent ... TRttiContext.getType(typeinfo(TNotifyEvent))
rendimenti TRttiType
istanza di un oggetto che vanta typekind = tkMethod
. sappiamo che la firma di TNotifyEvent è la procedura (mittente: TObject) dell'oggetto;
è possibile ottenere TRttiMethod
per questo? Voglio creare dinamicamente eventHandler per l'evento usando TRttiMethod.CreateImplementation()
o potrebbe esserci un altro modo per creare dinamicamente l'implementazione del metodo?
PS: l'idea è creare qualcosa come la catena di eventi. Al momento della compilazione non conosciamo il tipo di evento/firma, quindi possiamo utilizzare i generici per questo tipo di TEvenChain <TNotifyEvent>. Chain ha la raccolta sui gestori di eventi registrati, quindi, poiché non conosciamo il tipo di gestore in fase di compilazione, dobbiamo crearlo dinamicamente e il gestore riceve solo i parametri e le chiamate con il gestore registrato.
aggiornamento: ecco qualche codice (idea è di creare catena gestori di eventi):
procedure TMainForm.FormCreate(Sender: TObject);
begin
FEventChain := TNotifyChain.Create();
FEventChain.AddHandler(event1);
FEventChain.AddHandler(event2);
TestButton.OnClick := FEventChain.EventHandler;
end;
Event1
& event2
sono metodi (sender : TObject)
di forma; non è esempio generico (T in questo caso è NotifyEvent/Tchain <TNotifyEvent>) TEventChain.EventHandler
è TNotifyEvent
troppo
TNotifyChain
è
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
proprietà è associato a FEvent
variabile. E FEvent
non è assegnato poiché si presuppone che il tipo di evento/gestore sia sconosciuto.
così nel costruttore creiamo metodo virtuale con TNotifyEvent
firma e assegnare il suo codice a FEvent
:
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;
Qui uso TestNotifyHandler
metodo per creare gestore vero e proprio con la stessa firma utilizzando TRttimethod.CreateImplementation()
quindi suppongo , esiste un modo per creare l'implementazione del gestore eventi in fase di esecuzione utilizzando TRttiMethodType
da TNotifyEvent
perché contiene informazioni sul tipo/conteggio param e sulla convenzione di chiamata dell'evento effettivo utilizzato (nel caso generico).
Quanto lontano hai ottenuto ora, per favore condividi. – menjaraz
@menjaraz Non ho risolto questo problema. Non era un compito "reale" per me, "solo per divertimento". Ho scritto un articolo su questo nel mio blog: http://teran.karelia.pro/articles/item_4508.html (ma è originariamente in russo); puoi utilizzare Google per tradurlo in inglese [collegamento] http://translate.google.com/translate?sl=ru&tl=en&js=n&prev=_t&hl=ru&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F% 2Fteran.karelia.pro% 2Farticles% 2Fitem_4508.html & act = url – teran
Grazie per la risposta. – menjaraz