27 de agosto de 2009

Acessar propriedade de objeto Caché atravez do Delphi dinamicamente

A muito tempo que tive a necessidade de acessar uma propriedade de um objeto Caché no Delphi (via ActiveX) de forma dinamica e esta semana consegui com ajuda de algumas pesquisas na internet.

Os testes que realizei foram utilizando Delphi 2007 e Caché 5.0.21, porem, creio que pode funcionar em qualquer versão de Delphi e Caché.

O codigo abaixo demonstra como obter o valor de uma propriedade:

uses
  ComObj, ActiveX;

procedure TForm1.Button1Click(Sender: TObject);
var
    objFactory:variant;
    obj:OleVariant;
    nmProperty:PWideChar;
    vParam:Pointer;
    idDisp:integer;
    vlProperty:variant;
    idUserDefaultLC:integer;
begin
    /// Objeto que fará a conexão com o banco de dados.
    objFactory := CreateOleObject('CacheObject.Factory');

    /// Aqui selecionar o namespace "SAMPLES".
    objFactory.Connect(objFactory.ConnectDlg('Conexão'));

    /// Abro um objeto do banco de dados.
    obj := objFactory.OpenId('Sample.Person',10);

    /// Esta vai ser a propriedade que vou acessar de forma dinamica (atravez do nome).
    nmProperty := 'Name';

    idUserDefaultLC := GetUserDefaultLCID;

    IDispatch(obj).GetIDsOfNames(GUID_NULL, @nmProperty, 1, idUserDefaultLC, @idDisp);

    vParam := nil;
    IDispatch(Obj).Invoke(idDisp, GUID_NULL, idUserDefaultLC, DISPATCH_PROPERTYGET, vParam, @vlProperty, nil, nil);

    /// Aqui mostro o valor da propriedade que foi recuperado.
    ShowMessage(vlProperty);
end;

E este codigo abaixo demonstra como atribuir o valor a uma propriedade:

uses
  ComObj, ActiveX;

procedure TForm1.Button2Click(Sender: TObject);
var
    objFactory:variant;
    obj:OleVariant;
    nmProperty:PWideChar;
    idDisp:integer;
    idUserDefaultLC:integer;
    rDispParams:TDispParams;
    vlNew:OleVariant;
begin
    /// Objeto que fará a conexão com o banco de dados.
    objFactory := CreateOleObject('CacheObject.Factory');

    /// Aqui selecionar o namespace "SAMPLES".
    objFactory.Connect(objFactory.ConnectDlg('Conexão'));

    /// Abro um objeto do banco de dados.
    obj := objFactory.OpenId('Sample.Person',10);

    /// Valor antes de alterar.
    ShowMessage(obj.Name);

    /// Esta vai ser a propriedade que vou acessar/alterar de forma dinamica (atravez do nome).
    nmProperty := 'Name';

    idUserDefaultLC := GetUserDefaultLCID;

    IDispatch(obj).GetIDsOfNames(GUID_NULL, @nmProperty, 1, idUserDefaultLC, @idDisp);

    /// Novo valor que vou atribuir na propriedade.
    vlNew := 'alexandre';

    with rDispParams do
        begin
            rgvarg := @vlNew;
            rgdispidNamedArgs := @DispIDArgs;
            cArgs := 1;
            cNamedArgs := 1;
        end;

    IDispatch(obj).Invoke(idDisp, GUID_NULL, 0, DISPATCH_PROPERTYPUT, rDispParams, nil, nil, nil);

    /// Valor depois de alterar.
    ShowMessage(obj.Name);
end;

É isso ;) Agora quem gostar e for utilizar é só usar a imaginação para adicionar mais funcionalidades.

Obrigado a todos por lerem meu primeiro post, e fiquem a vontade para comentar e entrar em contato comigo para mais informações a respeito.

2 comentários:

  1. Muito bom o seu post. Este código também pode ser utilizado para acessar/setar propriedades de outras dll's. Fiz um teste com o código postado, porém utilizando outra dll e funcionou perfeitamente.

    []'s

    Rafael Camillis

    ResponderExcluir
  2. Legal Rafael! Se vc quizer fique a vontade para escrever um comentario junto com este seu exemplo.

    Abraço!

    ResponderExcluir