2012-04-17 14 views
7

Ho scritto una lingua di script per le mie applicazioni e il mio obiettivo è rendere possibile la pubblicazione di qualsiasi tipo da delphi nella sceneggiatura. Io uso rtti per automatizzare questo compito. Per ogni tipo di istanza come le classi, utilizzo il seguente codice per trovare e chiamare un metodo dallo script.Delphi - Invoke Metodo di registrazione per nome

var Info : TRttiType; 
    Meth : TRttiMethod; 
    Param : TArray<TValue>; 
    Result : TValue; 
    AnyClass : TClass; 
begin 
    ... 
    Info := RttiContext.GetType(AnyClass); 
    Meth := Info.GetMethod('AMethod'); 
    Setlength(Param, 1); 
    Param[0] := TValue.From<Integer>(11); 
    Result := Meth.Invoke(ClassInstance, Param); 
    ... 
end; 

Ma con un record di questo codice non funziona, perché il tipo TRttiMethod non offre un metodo Invoke() per i tipi di record. Posso accedere alle informazioni sui metodi da Info.GetMethod ('AMethod') dal tipo di record.
Per esempio io ho un disco come questo:

TRecordType = record 
    Field1, Field2 : single; 
    procedure Calc(Value : integer); 
end; 

Così Qualcuno sa un modo per richiamare un metodo da un record se ho methodname o methodaddress?

+0

Hai appena reinventato [DWScript] (http://code.google.com/pwdwscript/)? –

+0

Grazie per il suggerimento, ma conosco DWScript. La mia lingua è intesa come interfaccia scriptable per un programma delphi in cui sono possibili costrutti come AObject.AFunction.AObject.DoSomething. – DragonFlyOfGold

+2

Pensavo che DWScript potesse fare tutto questo, ma forse ho sbagliato –

risposta

12

Dopo aver esplorato i collegamenti nelle documentazioni delphi postati nei commenti sopra ho dato un'occhiata più da vicino al tipo delphi TRttiRecordMethod in System.Rtti. Fornisce il metodo DispatchInvoke() e questo metodo si aspetta un puntatore. Così seguente codice funziona:

TRecordType = record 
    Field1, Field2 : single; 
    procedure Calc(Value : integer);  
end; 


    Meth : TRttiMethod; 
    Para : TRttiParameter; 
    Param : TArray<TValue>; 
    ARec : TRecordType; 
begin 
    Info := RttiContext.GetType(TypeInfo(TRecordType)); 
    Meth := Info.GetMethod('Calc'); 
    Setlength(Param, 1); 
    Param[0] := TValue.From<Integer>(12); 
    Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
end; 

Se si desidera chiamare un metodo statico o operatore di overload il codice non funziona. Delphi aggiunge sempre internamente il puntatore automatico alla lista parametri, ma ciò causerà una violazione di accesso. Quindi utilizza questo codice:

Meth : TRttiMethod; 
    Para : TRttiParameter; 
    Param : TArray<TValue>; 
    ARec : TRecordType; 
begin 
    Info := RttiContext.GetType(TypeInfo(TRecordType)); 
    Meth := Info.GetMethod('&op_Addition'); 
    ... 
    Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
    Result := System.Rtti.Invoke(Meth.CodeAddress, Param, Meth.CallingConvention, Meth.ReturnType.Handle, Meth.IsStatic); 
end;  
+0

Grazie, questo mi ha davvero aiutato nella mia ricerca di un modo per chiamare dinamicamente un servizio web SOAP! – dahook