E 'possibile chiamare una funzione il cui nome è memorizzato in una stringa in Delphi?Delphi: Chiamare una funzione il cui nome è memorizzato in una stringa
risposta
Si prega di fornire maggiori dettagli su che cosa stai cercando di ottenere.
Per quanto ne so:
- Non è possibile chiamare una funzione random del genere.
- Per le funzioni classe e oggetto (MyObject.Function) questo può essere fatto con RTTI, ma è molto lavoro.
- Se hai solo bisogno di chiamare un particolare tipo di funzioni (ad esempio, funzione (numero intero, intero): stringa), è molto più semplice.
Per l'ultimo, dichiarare un tipo di funzione, quindi ottenere un puntatore a funzione e gettato in questo modo:
type
TMyFuncType = function(a: integer; b: integer): string of object;
TMyClass = class
published
function Func1(a: integer; b: integer): string;
function Func2(a: integer; b: integer): string;
function Func3(a: integer; b: integer): string;
public
function Call(MethodName: string; a, b: integer): string;
end;
function TMyClass.Call(MethodName: string; a, b: integer): string;
var m: TMethod;
begin
m.Code := Self.MethodAddress(MethodName); //find method code
m.Data := pointer(Self); //store pointer to object instance
Result := TMyFuncType(m)(a, b);
end;
{...}
//use it like this
var MyClass: TMyClass;
begin
MyClass := TMyClass.Create;
MyClass.Call('Func1', 3, 5);
MyClass.Call('Func2', 6, 4);
MyClass.Destroy;
end.
Deve essere possibile. Se VB6 può farlo, certamente Delphi deve permetterlo. – itsols
Se stai chiedendo se c'è qualcosa come il eval()
JavaScript è possibile in Delphi, no questo non è (facilmente) realizzabile poiché Delphi compila il codice nativo.
Se è necessario solo per supportare alcune stringhe si può sempre fare molte if
o un case
... Qualcosa di simile:
if myString = 'myFunction' then
myFunction();
L'ho fatto in VB6 e ** è ** una lingua nativa. Quindi credo che sia possibile anche con Delphi (e nel mio caso Lazarus Pascal) – itsols
Si può fare qualcosa di simile per la lavorazione di una o più classi con proprietà pubblicati che utilizzare le funzioni per implementare le funzionalità di lettura e scrittura. Le proprietà possono quindi essere scoperte utilizzando la riflessione RTTI e referenziate, causando il richiamo delle funzioni sottostanti.
In alternativa, è possibile memorizzare i puntatori alle funzioni in una tabella, o anche la proprietà oggetto di TStringList ed efficace li indice nome di stringa.
Diritto chiamata di una funzione per nome non è possibile in Delphi.
E ', per le funzioni di classe. RTTI può essere memorizzato anche per loro, anche con parametri e dettagli della convenzione di chiamata. Ma è PITA. – himself
Mi sorprende che nessuno ha suggerito un dispatch table. Questo è esattamente ciò che è per.
program RPS;
uses
SysUtils,
Generics.Collections;
type
TDispatchTable = class(TDictionary<string, TProc>);
procedure Rock;
begin
end;
procedure Paper;
begin
end;
procedure Scissors;
begin
end;
var
DispatchTable: TDispatchTable;
begin
DispatchTable := TDispatchTable.Create;
try
DispatchTable.Add('Rock', Rock);
DispatchTable.Add('Paper', Paper);
DispatchTable.Add('Scissors', Scissors);
DispatchTable['Rock'].Invoke; // or DispatchTable['Rock']();
finally
DispatchTable.Free;
end;
end.
L'implementazione che ho scritto utilizza i generici in modo che funzionasse solo con Delphi 2009+. Per le versioni precedenti sarebbe probabilmente più semplice implementare utilizzando TStringList e command pattern
+1 per l'idea, in particolare per Delphi 2009 e precedenti. Con Delphi 2010+, RTTI ha già tutte le informazioni sottostanti, quindi la risposta di Mohammed e Henri è più semplice. –
Pagina non trovata. – ZzZombo
Seriamente? SO spostato/eliminato una domanda senza aggiornare i collegamenti dal proprio sito web? –
Non hai specificato la tua versione Delphi, tuttavia se hai Delphi 2010 (+) puoi farlo usando il RTTI avanzato, non lo sono esperto di loro, ma ho provato questo campione per voi:
TProcClass = class
public
procedure SayHi;
function GetSum(X,Y:Integer): Integer;
end;
uses
Rtti;
{ TProcClass }
procedure TProcClass.SayHi;
begin
ShowMessage('Hi');
end;
function TProcClass.GetSum(X, Y: Integer): Integer;
begin
ShowMessage(IntToStr(X + Y));
end;
procedure ExecMethod(MethodName:string; const Args: array of TValue);
var
R : TRttiContext;
T : TRttiType;
M : TRttiMethod;
begin
T := R.GetType(TProcClass);
for M in t.GetMethods do
if (m.Parent = t) and (m.Name = MethodName)then
M.Invoke(TProcClass.Create,Args)
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ExecMethod('SayHi',[]);
ExecMethod('GetSum',[10,20]);
end;
Le buone cose, se si dispone di procedura o funzione con parametri che funzionerà senza più lavoro.
Si noti che questo codice perde almeno un'istanza 'TProcClass' per ogni metodo chiamato in questo modo. –
con Delphi 2010 è la utilizza JSON e SuperObject per richiamare il metodo con parametters.
http://code.google.com/p/superobject/source/browse/#svn/trunk
Se avete bisogno, c'è anche un parser XML per trasformare xml a JSON.
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure TestMethod(const value: string);
end;
var
Form1: TForm1;
implementation
uses superobject;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
SOInvoke(Self, 'TestMethod', SO('{value: "hello"}'));
end;
procedure TForm1.TestMethod(const value: string);
begin
Caption := value;
end;
È oltre il punto ma ha ancora a che fare con SuperObject. So che sei l'uomo giusto al posto giusto :-). Puoi prestare un po 'di attenzione a [questa domanda] (http://stackoverflow.com/q/7841617/744588) da qualche parte su SO? – menjaraz
Inserire ciascuna funzione in un'azione. Quindi è possibile trovare l'Azione per nome ed eseguirlo
function ExecuteActionByName(const S: String);
var
I: Integer;
begin
for I := 0 to MainForm.ComponentCount-1 do
if (MainForm.Components[I] is TAction)
and SameText(TAction(MainForm.Components[I]).Name,S) then
begin
TAction(MainForm.Components[I]).Execute;
Break;
end;
end;
+1; concetto interessante –
@RobMcDonell +1 per questa idea. Ho fatto una cosa simile nel vecchio VB6 e sto cercando di portarlo a Lazarus (che sono molto nuovo). Penso che la tua linea 'TAction (MainForm.Components [I]). Execute;' sia il fulcro dell'intera cosa. Volete indirizzarmi a un doc adatto sul comando? Anche una semplice spiegazione potrebbe fare. Grazie! – itsols
OK, io sono molto in ritardo alla festa, ma si può sicuramente chiamare le routine per nome con questo codice (Ci sono alcune limitazioni pensiero)
type
TExec = procedure of Object;
// rest of section...
procedure TMainForm.ExecuteMethod(MethodName : String);
var
Exec : TExec;
Routine : TMethod;
begin
Routine.Data := Pointer(Form1);
Routine.Code := Form1.MethodAddress(MethodName);
if Not Assigned(Routine.Code) then
Exit;
Exec := TExec(Routine);
Exec;
end;
Solo nel caso qualcuno ha bisogno di questo per Delphi 7/2010
Scusami - Sono abbastanza nuovo su questa piattaforma. Come puoi assegnare un valore come quello che hai fatto nella prima linea?Che tipo di dati è TExec? – itsols
@itsols: Certo ho modificato la mia risposta, in pratica metti la riga che dice 'TExec = procedura di Object;' solo * dopo * la parola chiave 'type' e questo è – TheDude
+1 per quello ... È chiaro ora :) Grazie! – itsols
- 1. Esiste una funzione Scala che consente di chiamare un metodo il cui nome è memorizzato in una stringa?
- 2. È possibile chiamare una funzione C, dato il suo nome come una stringa?
- 3. In Perl, come posso chiamare un metodo di cui ho il nome in una stringa?
- 4. Accesso valore della variabile in cui il nome della variabile viene memorizzato in una stringa in R
- 5. AngularJS - bind ng-model a una variabile il cui nome è memorizzato all'interno di un'altra variabile
- 6. chiama una funzione clojurescript per nome stringa
- 7. Come posso chiamare una funzione Delphi che restituisce una stringa usando JNA?
- 8. Chiamare la funzione nidificata quando il nome della funzione viene passato come una stringa
- 9. Utilizzare una stringa per chiamare la funzione in Python
- 10. Chiamare una funzione DLL delphi dal codice C#
- 11. Esecuzione operazione matematica quando l'operatore è memorizzato in una stringa
- 12. Come chiamare la funzione utilizzando il valore memorizzato in una variabile?
- 13. Come posso chiamare un nome di funzione definito in una stringa letterale in perl?
- 14. come chiamare una funzione in funzione plsql
- 15. come chiamare dinamicamente una funzione in C#
- 16. Come salvare una stringa in un file .txt in Delphi?
- 17. Python può chiamare le funzioni Delphi in una DLL?
- 18. Quick padding di una stringa in Delphi
- 19. MYSQL si unisce a una tabella il cui nome è memorizzato come valore di campo su un'altra tabella
- 20. Come chiamare una funzione, PostgreSQL
- 21. Emitting IL chiamare una funzione matematica
- 22. Come chiamare una funzione su una variabile in PHP?
- 23. come chiamare una stored procedure in cui clausola di SQL
- 24. Come chiamare una funzione con il suo nome (std :: string) in C++?
- 25. Chiamare una funzione solo una volta
- 26. Chiamare una funzione prima principale
- 27. Come si converte un nome di funzione in una stringa
- 28. Come chiamare una funzione in AngularJs quando il percorso coincide?
- 29. Come ottenere un browser Web per scaricare un file che è memorizzato in una stringa JavaScript?
- 30. Come trasformare una stringa in una chiamata di funzione JavaScript?
Se lo è, è ancora una cattiva idea (se non in casi molto rari). Cosa devi fare? – delnan
@delnan Perché questa è una cattiva idea? Sto cercando, ad esempio, di implementare alcuni pulsanti creati dinamicamente come comandi di menu. Le funzioni da chiamare per ciascuna vengono estratte da un DB e inserite in un array. Quindi chiamo la procedura il cui nome è in un elemento dell'array, quando si fa clic su un particolare pulsante. Penso che sia carino. Perché è una cattiva idea? In realtà sto provando questo su Lazarus Pascal (simile a Delphi) – itsols
@itsols Oltre a vari problemi tecnici (che * sono * importanti, ma richiedono spazio per spiegare e non * sempre * si applicano), l'obiezione principale è che confonde i nomi delle variabili con i dati dell'applicazione. Ned Batchelder ha scritto su confusione simile, nel contesto di una lingua in cui è in realtà facile da fare: [Tenere i dati fuori dai nomi delle variabili] (http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html). Usando le funzioni di prima classe più una struttura di dati di mappatura, o un'istruzione 'case', puoi ottenere la stessa cosa senza confondere i due. – delnan