• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 347
  • Last Modified:

TTable copy (assign ?)

Hi all,

I have a component that is very similar to a TTable, and the problem I need to solve occurs in TTable too, so I´ll use TTable in my example:

I need to make a "copy" of a TTable instance, so I can change some properties and then "restore" the original condition. I tried this code:

   Table2.Assign(Table1);
   ... Changes
   Table1.Assign(Table2);

But I got a message Can not assign a TTable to a TTable.

Why ? Any workaround ?

TIA,
Itamar
0
itamar
Asked:
itamar
  • 8
  • 7
1 Solution
 
hubdogCommented:
because ttable does not override the virtual assign method of tpersistent.
ttable.assign method no use.
you must write  a new component and override the assign method of tpersistent by yourself.

good luck

hubdog
0
 
hubdogCommented:
you can look the source of tpersistent.assign.it is very simple .then you will see it.

good luck

hubdog
0
 
itamarAuthor Commented:
Well,

i think there is no other way but write all the code to assign every property of my component with the source values...

I think that should be a clever way to copy two instances of the same object, perhaps using streams... WriteComponent...

still listening...

Thanks,
Itamar
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
brunoheCommented:
This is a serious problem. There is no other way to copy property values than using you own derived class from TTable and overwrite Assign method.

Anything else would be a hack.
0
 
itamarAuthor Commented:
Well,

i think there is no other way but write all the code to assign every property of my component with the source values...

I think that should be a clever way to copy two instances of the same object, perhaps using streams... WriteComponent...

still listening...

Thanks,
Itamar
0
 
hubdogCommented:
as you have said , maybe you can use stream to copy a table
procedure TForm1.Button1Click(Sender: TObject);
var
  b:tmemorystream;
  a:Ttable;
begin
  b:=TmemoryStream.Create;
  b.WriteComponent(table1);
  b.Position:=0;
  RegisterClass(TTable);
  TComponent(a) := b.ReadComponent(nil);
  showmessage(a.name);
  b.free;
end;

good luck

hubdog
0
 
itamarAuthor Commented:
Hi hubdog,

i think this is a good way. But I tried:

procedure TTable.Assign(Source: TPersistent);
var
   MStream: TMemoryStream;
begin
   if Source is TTable then begin
   MStream := TMemoryStream.Create;
   MStream.WriteComponent(TComponent(Source));
   MStream.Position := 0;
   RegisterClass(TTable);
   TComponent(Self) := MStream.ReadComponent(nil);
   MStream.Free;
   end
   else
      inherited Assign(Source);
end;

There is no compiler or run-time error, but in the code below I can´t restore the original property value:

procedure TForm1.Button1Click(Sender: TObject);
var
   Copy: TTable;
begin
   Table1.Filter := 'X=0';
   Copy := TTable.Create(Self);
   Copy.Assign(Table1); // Save
   ShowMessage('Old filter: ' + Copy.Filter);
   Table1.Filter := 'dummy';
   ShowMessage('Table1.Filter = ' + Table1.Filter);
   Table1.Assign(Copy); // Restore
   ShowMessage('Table1.Filter = ' + Table1.Filter); //Should be 'X=0'
end;

Any ideas ???
0
 
hubdogCommented:
here is my program ,it is ok
procedure TForm1.Button1Click(Sender: TObject);
var
  b:tmemorystream;
begin
  table1.filter:='x=0';
  b:=TmemoryStream.Create;
  b.WriteComponent(table1);
  b.Position:=0;
  RegisterClass(TTable);
  TComponent(table2) := b.ReadComponent(nil);
  showmessage(table2.filter);//it do show x=0
  b.free;
end;
I do not know where you write your assign method.Do you change the vcl-source or write in your own program? maybe that is the problem.
I think you should paste more source

good luck

hubdog
0
 
itamarAuthor Commented:

You´re right ! Your code works, but I have decided to go further and use TMemoryStream to write a code for the Assign method of my component (overrided) - see the question text.
0
 
hubdogCommented:
procedure ttable.assign
   .....
   RegisterClass(TTable);
   TComponent(Self) := MStream.ReadComponent(nil);
   MStream.Free;
   showmessage(self.filter);//it do show 'x=0' .So I think self maybe is destroied after exit the procedure so the copy is not correctly setted the property.That is only a guess.
   .....

good luck

hubdog
0
 
hubdogCommented:
when i trace into assign
I found
@copy =$12f6b7
@self =$12f690

the two address not equal.
so i guess you should not use self

regards,hubdog
0
 
itamarAuthor Commented:
so...
0
 
hubdogCommented:
i guess the real reason is
  TComponent(Self) := MStream.ReadComponent(nil);
  this code create a new self which is not equal to previous self.

hubdog
0
 
itamarAuthor Commented:
wow !

It makes sense ! If you can go deeper, please let me know...

tkx
0
 
hubdogCommented:
because
  if code is
        ......
   {TComponent(self) := MStream.ReadComponent(nil);}

   MStream.Free;
   self.Filter:='a';
   end
   else
      inherited Assign(Source);

then copy.filter:='a';
if the code is
        ......
   TComponent(self) := MStream.ReadComponent(nil);

   MStream.Free;
   self.Filter:='a';
then copy.filter:='';
0
 
itamarAuthor Commented:
think we're done with this question.

Thanks,
Itamar
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now