quarta-feira, 27 de fevereiro de 2008

MethodAddress

Método definido em TObject, retorna o endereço de um método published. Ou seja, um método definido na seção “published”. Entretanto, evocar o “MethodAddress” não é algo tão trivial. É preciso criar uma variável do tipo “procedure” que receberá o ponteiro para o método retornado por “MethodAddress”.
Exemplo 1:


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;

type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
private

public

published
procedure MyZnMethod;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
AuxProcedure: Procedure(Sender: TObject);
begin
AuxProcedure := Self.MethodAddress('MyZnMethod');
AuxProcedure(Self);
end;

procedure TForm1.MyZnMethod;
begin
Self.Caption := 'Estação ZN';
Self.Color := clAqua;
Self.Update;
Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

end.



Ok, muito simples! Só que se eu desejar evocar um método que está definido em outra classe terei de usar uma estratégia, pois o método MethodAddress, só conhece os métodos definidos na própria classe. Para exemplificar, vamos criar uma classe ‘TMyZnClassDummy’ e no mesmo evento OnClick do BitBtn1 evocar o método “Dummy” da nova classe, “TMyZnClassDummy”. Exemplo2:


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;

type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
private

public

ppublished
procedure MyZnMethod;
end;

type
TMyZnClassDummy = Class(TComponent)
private

protected
published
procedure Dummy;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
AuxProcedure: Procedure(Sender: TObject);
AuxProcedureBlah: Procedure(Sender: TObject);
begin
AuxProcedure := Self.MethodAddress('MyZnMethod');
AuxProcedure(Self);

(*Testando o Blah*)
ShowMessage('Testando o Blah!!');
AuxProcedureBlah := MethodAddress('Dummy');
AuxProcedureBlah(Self)
end;

procedure TForm1.MyZnMethod;
begin
Self.Caption := 'Estação ZN';
Self.Color := clAqua;
Self.Update;
Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

{ TMyZnClassDummy }

procedure TMyZnClassDummy.Dummy;
begin
ShowMessage(Self.Name + ' Blah!!!!');
end;

end.


Como eu posso fazer para conseguir executar o método “Dummy”? Eu preciso (primeiro, se for o caso fazer uses da unit onde a classe, cujo o método desejo evocar, se encontra) criar na classe que vai chamar através do “MethodAddress” um outro método pblished, este por sua vez chamara o método definido na outra classe. Vou Criar no Form1 um método que evocará o método “Dummy” da classe “TMyZnClassDummy”.Exemplo:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons;

type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
private

public

published
procedure MyZnMethod;
procedure ExeucteDummy;
end;

type
TMyZnClassDummy = Class(TComponent)
private

protected
published
procedure Dummy;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var
AuxProcedure: Procedure(Sender: TObject);
AuxProcedureBlah: Procedure(Sender: TObject);
begin
AuxProcedure := Self.MethodAddress('MyZnMethod');
AuxProcedure(Self);

(*Testando o Blah*)
ShowMessage('Testando o Blah!!');
(* Executo o Método procedure do Form1 "ExeucteDummy" *)
AuxProcedureBlah := MethodAddress('ExeucteDummy');
AuxProcedureBlah(Self)
end;

procedure TForm1.ExeucteDummy;
var
MyZnClassDummy: TMyZnClassDummy;
begin
MyZnClassDummy := TMyZnClassDummy.Create(Self);
try
MyZnClassDummy.Dummy;
finally
MyZnClassDummy.Free;
end;

end;

procedure TForm1.MyZnMethod;
begin
Self.Caption := 'Estação ZN';
Self.Color := clAqua;
Self.Update;
Self.Canvas.TextOut(12, 130, 'Dummy MethodAddress Teste Estação ZN!!!');
end;

{ TMyZnClassDummy }

procedure TMyZnClassDummy.Dummy;
begin
ShowMessage(Self.ClassName + ' Blah!!!!');
end;

end.

Baseado nisso, podemos criar um catálogo de métodos de classes distintas, os quais poderão ser exibidos numa interface, permitindo ao usuário uma forma de setup da aplicação. De maneira que ele possa definir que funcionalidade será executada a partir de uma determinada ação na interface. Sei que esse tipo de abordagem não é nada convencional, contudo acredito ela permita um flexibilização poderosa para algumas situações.


"A mente que se abre a uma nova idéia jamais voltará ao seu tamanho original". Albert Estein

Nenhum comentário:

Postar um comentário