2012-04-17 12 views
7

Napisałem skryptowy język dla moich aplikacji i moim celem jest umożliwienie publikowania dowolnego typu z delphi w skrypcie. Używam rtti do automatyzacji tego zadania. Dla każdego typu instancji, takiego jak klasy, używam następującego kodu, aby znaleźć i wywołać metodę ze skryptu.Delphi - Metoda Invoke Record na nazwę

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; 

Ale rekord ten kod nie zadziała, ponieważ typ TRttiMethod nie oferuje metodę Invoke() dla typów rekordów. Mogę uzyskać dostęp do informacji o metodach przez Info.GetMethod ("AMethod") z rodzaju rekordu.
Na przykład mam zapis takiego:

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

Więc czy ktoś wie sposób, aby wywołać metodę z rekordem jeśli mam methodName lub methodaddress?

+0

Czy właśnie wymyśliłeś [DWScript] (http://code.google.com/p/dwscript/)? –

+0

Dzięki za podpowiedź, ale znam DWScript. Mój język jest przeznaczony jako skryptowalny interfejs do programu delphi, w którym możliwe są konstrukcje takie jak AObject.AFunction.AObject.DoSomething. – DragonFlyOfGold

+2

Pomyślałem, że DWScript może to wszystko zrobić, ale może się mylę. –

Odpowiedz

12

Po zapoznaniu się z linkami w dokumentacji delphi zamieszczonymi w komentarzach powyżej, przyjrzałem się bliżej typowi delphi TRttiRecordMethod w System.Rtti. Dostarcza metodę DispatchInvoke(), a ta metoda oczekuje wskaźnika. więc następujący kod działa:

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; 

Jeśli chcesz wywołać metody statycznej lub przeciążony operator kod nie działa. Delphi wewnętrznie zawsze dodaje własny wskaźnik do listy parametrów, ale spowoduje to zmianę dostępu. Dlatego użyj tego kodu:

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

Dzięki, pomogło mi to w moim dążeniu do dynamicznego wywołania usługi SOAP! – dahook