5

I have few class helpers for components to create sub-components, like popup menus, to access this sub-components in run time, I create a Singleton TDictionary.

My question is how do I know that the owner-component is being destroyed to remove the sub-component from the TDictionary?

If it is a specialized component I add it in the destructor, but I cannot add constructor and/or destructor in the class helper.

Edit - Solution

I created a base object that accepts TObject as parameters, when used, the remove action must be done manually.

Then I inherited a new class from it, override the methods to accept only TComponent. This is how the relevant part of the code is now:

type     
  TCustomLinkedComponents = class(TCustomLinkedObjects)
  strict private
    type
      TCollector = class(TComponent)
      protected
        procedure Notification(AComponent: TComponent; Operation: TOperation); override;
      end;
  strict private
    FCollector: TCollector;
[..]
  end;

procedure TCustomLinkedComponents.Add(Owner: TComponent; const LinkedName: string; LinkedComponent: TComponent);
begin
  inherited Add(Owner, LinkedName, LinkedComponent);
  FCollector.FreeNotification(LinkedComponent);
end;

procedure TCustomLinkedComponents.TCollector.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if Operation = opRemove then
    LinkedObjects.Remove(TObject(AComponent));
end;

Using this approach I can resolve my actual need and let opened to be easily extented latter.

Cesar Romero
  • 4,027
  • 1
  • 25
  • 44

3 Answers3

5

Instead of a TDictionary, make a custom TComponent descendant that contains a TDictionary. Then look into how TComponent.FreeNotification works, and the solution should become obvious. :)

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • Hi Mason, it will work for components, but I want something more generic to use with TObjects. – Cesar Romero Aug 01 '12 at 19:21
  • @Cesar: Then you're out of luck. There's no way to tell "if an object is being created or destroyed inside a class helper," and your code shouldn't have to know that. What it does need to know is who holds a reference to what, so it can clean things up properly. If you can't use the TComponent notification system, you have to implement something like it yourself. – Mason Wheeler Aug 01 '12 at 20:42
  • 2
    You could hook `TObject.FreeInstance` to make it work for any object. – Stefan Glienke Aug 01 '12 at 22:11
2

If you want to know if the component is being destroyed, you should use

function IsBeingDestroyed(AComponent : TComponent) : Boolean;
begin
  Result := csDetroying in AComponent.ComponentState;
end;

If you want to be notified when it is being destroyed, using FreeNotification is the way to go.

For a little more detail on FreeNotification, you can check this post.

Community
  • 1
  • 1
Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • 2
    But `TDictionary` is not a component. – TLama Aug 01 '12 at 19:21
  • Hi Ken, see my comment to Mason, I want it working for TObject. – Cesar Romero Aug 01 '12 at 19:21
  • @TLama, And it doesn't need to. It would make thing slightly easier, sure, but not required. It would just require a TComponent instance that goes hand in hand with his TDictionary to manage the FreeNotifications in the same way the TComponentList class works. – Ken Bourassa Aug 01 '12 at 20:07
  • @Ken, I know, but you forgot to mention in your post, that OP needs to *wrap* his dictionary into a component. – TLama Aug 01 '12 at 20:13
  • @Cesar, If what you want is possible at all, it would be down the "ugly hack road", and believe me, you don't want to go there. If there was an elegant way to do that with TObject, I doubt they would have re-implemented it in TComponent. (Though anything is possible) – Ken Bourassa Aug 01 '12 at 20:16
2

No you can't. Delphi does not keep special track whether or not something is created/destroyed by a class helper.

Jeroen Wiert Pluimers
  • 23,965
  • 9
  • 74
  • 154