Is it possible to clone objects in Delphi?

8

Is it possible to clone objects in Delphi at runtime?

For example, you have a Data Module with a zTable . If I use this zTable on two screens at the same time, with different filters, the second screen will overlap the filter used by the first one.

Is it possible for me to use this zTable as a template and in onShow of my form I create a clone of it?

    
asked by anonymous 10.02.2014 / 17:29

4 answers

2

Following the tips from @Gunar Bastos I was able to find a solution to my problem. Follow below:

function CopiarDataSet(zTableOriginal: TDataset): TJvMemoryData;
var
    i:integer;
begin
    //Abrindo o dataset original
    zTableOriginal.Open;

    //Criando o clone e copiando a estrutura do original
    Result := TJvMemoryData.Create(Application);
    Result.CopyStructure(zTableOriginal);

    //Abrindo o clone
    Result.Open;

    //Movendo o cursor para o primeiro registro do dataset original
    zTableOriginal.First;

    //Iteração para copiar os dados do original para o clone
    while not(zTableOriginal.Eof) do begin

        //Preparando o clone para receber os dados
        Result.Insert;

        //Iteração sobre os campos da tabela
        for i := 0 to zTableOriginal.FieldCount - 1 do begin
                //Copiando os dados
                Result.FieldByName(zTableOriginal.Fields[i].FieldName).Value := zTableOriginal.Fields[i].Value;

                //Copiando os labels das colunas
                Result.FieldByName(zTableOriginal.Fields[i].FieldName).DisplayLabel := zTableOriginal.Fields[i].DisplayLabel;
        end;

        //Efetivando a inserção
        Result.Post;

        //Indo para o próximo registro do dataset original
        zTableOriginal.Next;
    end;

    //Fechando o dataset original
    zTableOriginal.Close;

end;
    
21.02.2014 / 19:50
6

Depending on the class, you give ...

Try to create a zTable at runtime and use the command:

        zTableCriada.Assign(zTableOriginal);

Let me explain: The Assign serves to get 'in thesis' all the data of another component of the same class and copy them to itself, in its instance. The problem is that this is not automatic; When the scheduler of the class in question is writing it (in this case, the zTable developer), it must manually program the procedure Assign, or it will give 'not implemented' error. So, go do a test, because I do not have the components installed here.

If it does not work, there are several ways you can do what you want. Anything will give you some ideas here.

    
10.02.2014 / 17:53
4

In this case it will not be possible for you to clone the content of zTable (assuming it is a Table component of Zeos) because it is a component whose contents are retrieved directly from the data server.

In your case, it would be better to have your implementation (actually, your entire application) based on the TClientDataset component. This component allows your content to be cloned in order to provide the functionality you need, which is to have the same records already selected in another context, for another use, without interfering with the original component.

In your specific case, my best suggestion is to study TClientDataset and TDatasetProvider and thus reform your DataModule to make use of this component. Then you will add a Clone method to this DataModule that will produce the replica of it to be used in the other place without interfering with the original instance.

    
11.02.2014 / 14:38
4

If the desire is simply to clone objects, Delphi supports this through the TPersistent.Assign method which is the ancestor of the TComponent class, which serves as the basis for the visual and non-visual components of Delphi.

This method takes the contents of an object (the passed by parameter) into the new one, and would look something like this in the following style

procedure ClonazTable(zTableOriginal: TDataset);
begin
  zTableClonada.Assign(zTableOriginal);
end;

Another option is to clone objects through Rtti, traversing the object and copying the data from one to the other. There is a good article on the subject in the magazine CLube Delphi number 113.

However since this component is a database query, the information that is fetched from the database will not be cloned together. To do this you need to copy the entire structure of the dataset to something that exists exclusively in memory, such as a TClientDataset.

To do this, you need to first copy the structure and then the data from the original DataSet to the DataSet in Memory, two of the many options that exist to make this work easier are:

1. TJvMemoryData : A component of the Jedi package (which is free), it has a method that copies the structure of a Dataset to the component, leaving only the work of copying the data.

function CopiarDataSet(zTableOriginal: TDataset): TJvMemoryData;
begin
  Result := TJvMemoryData.Create(Application);
  **Result.CopyStructure(zTableOriginal);**
  zTableOriginal.First;
  while not(zTableOriginal.Eof) do
  begin
    ***//Código que copia os dados***
    zTableOriginal.Next;
  end;
end;

2. TdxMemData : A component of the Developer Express package (which is paid for), it has a method that completely copies the Dataset to a new one.

function CopiarDataSet(zTableOriginal: TDataset): TdxMemData;
begin
  Result := TdxMemData.Create(Application);
  **Result.CopyFromDataSet(zTableOriginal);**
end;
    
20.02.2014 / 13:22