Class TFreeNotificationObserver

Unit

Declaration

type TFreeNotificationObserver = class(TComponent)

Description

Observe when something is freed, and call an event then. You need to set Observed of this component to make it notified about freeing of something. When the Observed is freed, this component will make OnFreeNotification event.

An example code using it:

type
  TChild = class(TComponent)
  end;

  TContainer = class(TComponent)
  private
    FChild: TChild;
    FChildObserver: TFreeNotificationObserver;
    procedure SetChild(const Value: TChild);
    procedure ChildFreeNotification(const Sender: TFreeNotificationObserver);
  public
    constructor Create(AOwner: TComponent);
    property Child: TChild read FChild write SetChild;
  end;

implementation

constructor TContainer.Create(AOwner: TComponent);
begin
  inherited;
  FChildObserver := TFreeNotificationObserver.Create(Self);
  FChildObserver.OnFreeNotification := @ChildFreeNotification;
end;

procedure TContainer.SetChild(const Value: TChild);
begin
  if FChild <> Value then
  begin
    FChild := Value;
    FChildObserver.Observed := Value;
  end;
end;

procedure TContainer.ChildFreeNotification(const Sender: TFreeNotificationObserver);
begin
  FChild := nil;
end;

Using this is an alternative to observing freeing using standard TComponent.FreeNotification / TComponent.RemoveFreeNotification mechanism https://castle-engine.io/modern_pascal_introduction.html#_free_notification . Using TFreeNotificationObserver is:

  • A bit simpler and it's harder to make a mistake.

    E.g. the line FChildObserver.Observed := Value is simpler than the typical equivalent lines required to unregister notification of the old value and register notification of the new value. (See https://castle-engine.io/modern_pascal_introduction.html#_free_notification example of FreeNotification usage.)

  • The TContainer doesn't need to descend from TComponent.

    You can manually free FChildObserver in the TContainer.Destroy.

  • Reliable if one class wants to observe freeing of multiple properties, and some of those properties may be sometimes equal. In this case using FreeNotification / RemoveFreeNotification with the main class would be unreliable (as RemoveFreeNotification removes the notification, even if you registered to it twice by FreeNotification), and requires complicated code to handles these special cases.

    Using this component as a "proxy" to track each property is simpler, there's no additional code to handle this case. You just need different observer for each property to be observed.

Hierarchy

  • TObject
  • TPersistent
  • TComponent
  • TFreeNotificationObserver

Overview

Methods

Protected procedure Notification(AComponent: TComponent; Operation: TOperation); override;
Public destructor Destroy; override;

Properties

Public property OnFreeNotification: TFreeNotificationEvent read FOnFreeNotification write FOnFreeNotification;
Public property Observed: TComponent read FObserved write SetObserved;

Description

Methods

Protected procedure Notification(AComponent: TComponent; Operation: TOperation); override;
 
Public destructor Destroy; override;
 

Properties

Public property OnFreeNotification: TFreeNotificationEvent read FOnFreeNotification write FOnFreeNotification;

Called when we receive notification that something was freed.

Public property Observed: TComponent read FObserved write SetObserved;

Setting this property makes the given component observed, freeing it will make OnFreeNotification. When setting, the previous value of this property stops being observed.

Note that this property will be automatically changed to Nil after OnFreeNotification, if the OnFreeNotification will not change it. This is necessary (we need to detach our "free notification" from a component that will be freed) and makes it safer (we will not expose dangling pointer).


Generated by PasDoc 0.16.0.