Executar Métodos de classe pelo nome e sem precisar dar uses da unit.
Oi amigos.
Está dica é mais avançada e também é um exemplo de uso da RTTI do Delphi.
Neste exemplo vamos executar um método de classe, sem declarar uses da unit onde está a classe e executar pelo nome do método.
Primeiramente vamos as explicações…
Passo 1
Para funcionar, a classe que detém o método deve ser descendente de TPersistent.
Exemplo:
TExemploClasse = class(TPersistent)
class function Teste(ANumber : Integer) : string;
end;
Passo 2
A Classe deve estar registrada
Exemplo:
initialization
RegisterClass(TExemploClasse);
Passo 3
Utilize esta função que criei para facilitar a vida
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
var
ctx : TRttiContext;
lType : TRttiType;
lMethod : TRttiMethod;
vClass : TClass;
begin
ctx := TRttiContext.Create;
vClass := FindClass(ClassName);
lType := ctx.GetType(vClass);
Result := nil;
try
if Assigned(lType) then
begin
lMethod := lType.GetMethod(MethodName);
if Assigned(lMethod) then
Result := lMethod.Invoke(vClass, MethosParams);
end;
finally
lMethod.Free;
lType.Free;
ctx.Free;
end;
end; |
function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
var
ctx : TRttiContext;
lType : TRttiType;
lMethod : TRttiMethod;
vClass : TClass;
begin
ctx := TRttiContext.Create;
vClass := FindClass(ClassName);
lType := ctx.GetType(vClass);
Result := nil;
try
if Assigned(lType) then
begin
lMethod := lType.GetMethod(MethodName);
if Assigned(lMethod) then
Result := lMethod.Invoke(vClass, MethosParams);
end;
finally
lMethod.Free;
lType.Free;
ctx.Free;
end;
end;
Veja que aqui você informa o nome da classe, o nome do método e possíveis parâmetros do mesmo.
Inclusive é possível obter retorno de funções.
Para um melhor entendimento, abaixo tem o fonte na integra de exemplo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
| unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, rtti, Vcl.StdCtrls;
type
{ Classe de exemplo, normalmente estará em outra unit }
TExemploClasse = class(TPersistent)
class function Teste(ANumber : Integer) : string;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
implementation
{$R *.dfm}
function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
var
ctx : TRttiContext;
lType : TRttiType;
lMethod : TRttiMethod;
vClass : TClass;
begin
ctx := TRttiContext.Create;
vClass := FindClass(ClassName);
lType := ctx.GetType(vClass);
Result := nil;
try
if Assigned(lType) then
begin
lMethod := lType.GetMethod(MethodName);
if Assigned(lMethod) then
Result := lMethod.Invoke(vClass, MethosParams);
end;
finally
lMethod.Free;
lType.Free;
ctx.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
vValue, vResult : TValue;
begin
vValue := 10;
vResult := ExecuteAwayMethod('TExemploClasse', 'Teste', vValue) ;
ShowMessage( vResult.AsString );
end;
{ TExemploClasse }
class function TExemploClasse.Teste(ANumber: Integer): string;
begin
Result := ANumber.ToString;
end;
{ Para uso deste exemplo, a classe precisa estar registrada }
initialization
RegisterClass(TExemploClasse);
end. |
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, rtti, Vcl.StdCtrls;
type
{ Classe de exemplo, normalmente estará em outra unit }
TExemploClasse = class(TPersistent)
class function Teste(ANumber : Integer) : string;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
implementation
{$R *.dfm}
function ExecuteAwayMethod(ClassName, MethodName : string;
MethosParams : array of TValue) : TValue;
var
ctx : TRttiContext;
lType : TRttiType;
lMethod : TRttiMethod;
vClass : TClass;
begin
ctx := TRttiContext.Create;
vClass := FindClass(ClassName);
lType := ctx.GetType(vClass);
Result := nil;
try
if Assigned(lType) then
begin
lMethod := lType.GetMethod(MethodName);
if Assigned(lMethod) then
Result := lMethod.Invoke(vClass, MethosParams);
end;
finally
lMethod.Free;
lType.Free;
ctx.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
vValue, vResult : TValue;
begin
vValue := 10;
vResult := ExecuteAwayMethod('TExemploClasse', 'Teste', vValue) ;
ShowMessage( vResult.AsString );
end;
{ TExemploClasse }
class function TExemploClasse.Teste(ANumber: Integer): string;
begin
Result := ANumber.ToString;
end;
{ Para uso deste exemplo, a classe precisa estar registrada }
initialization
RegisterClass(TExemploClasse);
end.
Dúvidas ou sugestões? deixe o seu comentário.
Fonte de referência: https://stackoverflow.com/questions/8102255/delphi-dynamically-calling-different-functions
-
Giovani Da Cruz
-
8.870 views
- 0 comentários
- 27 de dezembro de 2018
Está gostando do conteúdo? Considere pagar um cafezinho para nossa equipe!
Posts Relacionados - Continue Aprendendo