0

I am developing a DataAware component and executing some code after the database is open.

This is the code I have at the moment:

  TMyDataAwareComponent = class(TDataAwareComponent)
  private
    { Private declarations }
    procedure ToBeExecutedOnAfterOpen(DataSet: TDataSet);
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  end;

 constructor TMyDataAwareComponent.Create(AOwner: TComponent);
 begin
  inherited;
  if Assigned(Self.DataSource) then
  begin
    Self.DataSource.DataSet.AfterOpen := ToBeExecutedOnAfterOpen;
  end;
 end;

 procedure TMyDataAwareComponent.ToBeExecutedOnAfterOpen(DataSet: TDataSet);
 var
  i: Integer;
 begin
    // Do something here
 end;

The code works correctly but the event AfterOpen of the dataset linked to the component is not fired any longer. How can I make sure the AfterOpen Event is fired first in the dataset and then in my component ?

Is there a solution valid for all events in the datasets (BeforeOpen, AfterOpen, BeforeCancel, BeforeDelete, AfterCancel, AfterDelete, ...etc) ?

3
  • 1
    The code works correctly but the event AfterOpen of the dataset linked to the component is not fired any longer. You hijacked it! Commented Jun 16, 2015 at 6:19
  • 1
    Writing data-aware components refer to the already completed one by Delphi authors. For single field editor look at TDBEdit and its FDataLink field; for grid-like components look at TDBGrid and its FDataLink field too. Commented Jun 16, 2015 at 9:48
  • You need to check that Self.DataSource.DataSet is Assigned, too, fwiw. Commented Jun 16, 2015 at 19:31

3 Answers 3

1

You can use a virtual method interceptor to intercept the DoAfterOpen virtual call

FVirtualIncerceptor := TVirtualMethodInterceptor.Create(TDataSet);
FVirtualIncerceptor.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
    const Args: TArray<TValue>; out DoInvoke: Boolean; out Result: TValue)
begin
  if Method.Name = 'DoAfterOpen' then
    ToBeExecutedOnAfterOpen(TDataset(Instance));
end;
FVirtualIncerceptor.Proxify(Self.DataSource.DataSet);

See this for more info http://docwiki.embarcadero.com/CodeExamples/XE8/en/TVirtualMethodInterceptor_(Delphi)

I assume you can see how to extend this to handle the other cases as well

Sign up to request clarification or add additional context in comments.

Comments

0

You would have to save old DataSet.AfterOpen on assignment and call that saved method in ToBeExecutedOnAfterOpen. But as Abelisto already said in his comment, this is not the way to go. It wouldn't pass your requirement to be "a solution valid for all events in the datasets" neither. Maybe this helps you: http://delphidabbler.com/tips/194

Comments

0

You might look at Aspect Oriented Programming. Like @Jasper pointed out...Virtual Method Injection...

DSharp comes to mind on setting this up easily. Look at DSharp.Aspects.Weaver. You can easily tie into any Method that is Published or Public.

-Rick

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.