Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you remove a published property from a delphi component and not cause errors on the forms where the component is used?

Tags:

delphi

I have a component that was developed by my company, and would like to remove one of the published properties that is no longer needed and clashes with the way the component works now.

Is there a way to remove the property and not cause property not found errors at runtime or design time when forms that use the component are loaded? i.e. Is there a way to make Delphi silently drop a component property?

like image 859
Amy Avatar asked Apr 27 '11 15:04

Amy


2 Answers

Yes. Just remove the property, then override DefineProperties and process it there. That will satisfy the streaming system by loading the value which you can just throw away. Be sure to do nothing when writing the stream.

like image 57
Allen Bauer Avatar answered Nov 06 '22 06:11

Allen Bauer


Depending on the property, the easiest would be to leave the property, but mark it as deprecated and just have the Read/Write bits point to a field that's never used.

Alternatively, you can override DefineProperties and call Filer.DefineProperty('PropertyName', ReadProc); where PropertyName is the property you've removed, and ReadProc is a function that calls various TReader Read* functions. This has the advantage that the properties aren't in your interface anymore.

For example, say you've removed this property:

property Center: TPoint read FPoint write SetPoint;

Here's what you would add to your component:

TMyComponent = class...
private
  procedure SkipReadPoint(Reader: TReader);
protected
  procedure DefineProperties(Filer: TFiler); override;
end;

procedure TMyComponent.DefineProperties(Filer: TFiler);
begin
  inherited;
  Filer.DefineProperty('Center', SkipReadPoint, nil, False);
end;

procedure TMyComponent.SkipReadPoint(Reader: TReader);
begin
  Reader.ReadListBegin;
  Reader.ReadInteger;
  Reader.ReadInteger;
  Reader.ReadListEnd;
end;

Skipping a simple type like Boolean or Integer is easier, since you can just call ReadBoolean or ReadInteger without bothering with the ReadList functions.

In our case we had a lot of similar properties across a bunch of classes (for CLX compatibility) so we had global "dummy" functions like this:

procedure DummyReadBool(Self: Pointer; Reader: TReader);
begin
  Reader.ReadBoolean;
end;
const
  SkipReadBool: TMethod = (Code: @DummyReadBool; Data: nil);

and then the DefineProperty call looks like this:

Filer.DefineProperty('PropName', TReaderProc(SkipReadBool), nil, False);

That way each class doesn't have to have duplicate Skip* functions.

like image 18
Zoë Peterson Avatar answered Nov 06 '22 08:11

Zoë Peterson