Para aqueles momentos que quero varrer todos os componetes que estão no FORM para pegar quem são e aplicar um operador   AS que tal usar um metódo anônimo para isto….

Forma tradicional

A forma tradicional de se varrer todos os componentes que estão sobre responsabilidade do FORM é fazer um loop com FOR e avaliar um-a-um até encontrar o que se deseja.

[code lang=”pascal”]

var  i:integer;
begin
for i := 0 to FormX.ComponentCount-1 do
begin
if FormX.Components[i] is TQuery then // quero pegar so as TQuery
with FormX.Components[i] as TQuery do
begin
close; // fechar a TQuery
end;
end;

end;
[/code]

 

Loop de Componentes com Anonimous Methods

Utilizando “Anonimous Methods” é um modelo não tradicional de olhar a mesma questão. Entender a estrutura de um “Anonimous Method” pode simplificar muitas operações de codifição do dia-a-dia e como exemplo de fundo vamos varrer os componentes dos formulários…

  • Criando um HELPER para separar a lógica (o LOOP)

    [code lang=”pascal”]
    type
    TComponentHelper = class Helper for TComponent

    public
    procedure ComponentsLoop(AProc: TProc<TComponent>; AChild: boolean = false);
    end;

    procedure TComponentHelper.ComponentsLoop(AProc: TProc<TComponent>; AChild: boolean = false);
    var
    i: integer;
    begin
    if assigned(AProc) then
    for i := 0 to ComponentCount – 1 do
    begin
    AProc(Components[i]);
    if AChild and (Components[i].ComponentCount > 0) then
    Components[i].ComponentsLoop(AProc, AChild);
    end;
    end;
    [/code]

  • Executando o LOOP utilizando o método anônimo do HELPER

    [code lang=”pascal”]

    procedure TForm39.Button1Click(Sender: TObject);
    begin
    Memo1.Lines.Clear;
    ComponentsLoop(
    Procedure(AComp: TComponent)
    begin
    // fecha todos os TDataset (TQuery)
    if AComp is TDataset then
    with AComp as TDataset do
    close;

    end, false);

    end;

    [/code]

 

Usando  Anonimous LOOP para um TList (genérico)

Quando vezes precisou fazer um loop em um TList….

  • Implementando um LOOP “anonimous” para o TList na classe HELPER

    [code lang=”pascal”]
    procedure TComponentHelper.ListLoop(AList: TList; AProc: TProc<TObject>);
    var
    i: integer;
    begin
    for i := 0 to AList.Count – 1 do
    AProc(AList[i]);
    end;

    [/code]

  • Aplicando o LOOP “anonimous” em um TList

    [code lang=”pascal”]
    procedure TForm39.Button3Click(Sender: TObject);
    var
    FList: TList;
    begin
    memo1.Lines.Clear;
    FList := TList.create;
    try
    PopularALista(FList);

    // fazer um LOOP usando Anonimous
    ListLoop(FList,
    procedure(AObj: TObject)
    begin
    memo1.Lines.Add( AObj.ClassName );
    end);

    finally
    FList.Free;
    end;
    end;

    [/code]

Parece Simples !!! Quantas vezes precisou escrever um LOOP em um TDataset (aka TQuery, TClientDataset)???

Código Exemplo  Helper para TDataset

 

 

Sabe todos aquelas linhas de código para incluir um item no menu “by code”…

  • inicializa o item de menu;
  • adiciona os parametros;
  • cria o método para o evento OnClick…
  • atribui o evento;
  • adiciona o item à lista;

Exemplo VCL para incluir um item de menu usando código:

[code]
procedure TForm40.ClickMenuItem(sender:TObject);
begin
showMessage(‘menu sem anonimous’);
end;
procedure TForm40.FormCreate(Sender: TObject);
var it:TMenuItem;
begin
it := TMenuItem.Create(MainMenu1);
it.caption := ‘Teste de um menu sem anonimous’;
it.OnClick := ClickMenuItem;
MainMenu1.Items.Add(it);
end;
[/code]

Métodos “anonimous” é uma poderosa ferramenta presente no Delphi na era XE, que encurta caminhos complexos. Ao reduzir código ao mesmo tempo aumentamos qualidade (com menor ocorrência de bugs) bem como menor tempo de implementação. Se considerar que o maior tempo se gasta em testes e correções de defeitos, então o ganho é exponencial.

Exemplo usando “Anonimous Method”:

[code]
uses VCL.Menus.Helpers;
procedure TForm40.FormCreate(Sender: TObject);
begin
MainMenu1.Items.CreateAnonimous(‘Teste menu com anonimous’,
procedure begin
showmessage(‘ok…’);
end);
end;
[/code]

Fontes: https://github.com/amarildolacerda/helpers

Lembra quantas vezes você precisou fazer um Loop em um Dataset para fazer uma soma, uma
contagem ou qualquer outra coisa…
Não gosto de fazer de novo algo que já fiz antes… Pensando nisto passei a usar “anonimous
method” do delphi para executar para mim os trechos repetitivos dos loops…
Veja como ficou.

[code lang=”pascal”]
type
TDatasetHelper = class helper for TDataset
public
procedure DoLoopEvent(AEvent: TProc<TDataset>); overload;
end;

procedure TForm34.execute;
var total:Double;
begin
// abere o Dataset com os dados.
alQuery1.sql.Text := ‘select codigo, total valor from sigcaut1 where data>=:data’;
alQuery1.ParamByName(‘data’).AsDateTime := strTodate(’01/01/2016′);
alQuery1.Open;
// fazer um loop para somar o total, usando metodos anonimos;
total := 0;
alQuery1.DoLoopEvent( procedure( ds:TDataset)
begin
total := total + ds.FieldByName(‘valor’).AsFloat; // executa o loop
end);
showMessage( FloatTOStr(total) ); // mostra o total da soma obtida no loop
end;

procedure TDatasetHelper.DoLoopEvent(AEvent: TProc;TDataset;);
var
book: TBookMark;
begin
book := GetBookmark;
try
DisableControls;
first;
while eof = false do
begin
AEvent(self);
next;
end;
finally
GotoBookmark(book);
FreeBookmark(book);
EnableControls;
end;
end;
[/code]

Código Original

A introdução de Class Helper no delphi ajudou o desenvolvedor a incluir novas
funcionalidades nas classes nativas do delphi – você tem uma idéia de um
recursos dos sonhos e gostaria de implementar lá na classe base, use Class
Helper.

Extendendo o TDataset:
[code lang=”pascal”]
TDatasetHelper = class helper for TDataset
public
procedure Run(AProc:TProc<TDataset>);
end;

procedure TDatasetHelper.Run(AProc: TProc<TDataset>);
begin // executa em um thread separada
TThread.CreateAnonymousThread(
procedure begin
if assigned(AProc) then
AProc(self);
end
).Start;
end;
[/code]
O exemplo implementa a capacidade de uso da “procedure” RUN(…) por
qualquer classe com herança de TDataset.

Trabalhando com o novo procedimento:

O procedimento RUN por finalidade executar em um processo paralelo (uma
nova TThread) a rotina que estiver implementando no TProc.
[code lang=”pascal”]
var total:double;
begin
query1.run(
procedure (ds:TDataset) // rotina a executar em paralelo.
begin
ds.first;
while ds.eof=false do
begin
total := total + xxxxx;
ds.next;
end;
end);
end;

[/code]