Delphi 中的组件事件检测

Component event detection in Delphi

我正在开发 DataAware 组件并在数据库打开后执行一些代码。

这是我目前的代码:

  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;

代码工作正常,但链接到组件的数据集的 AfterOpen 事件不再触发。 如何确保 AfterOpen 事件首先在数据集中触发,然后在我的组件中触发?

是否有对数据集中的所有事件(BeforeOpen、AfterOpen、BeforeCancel、BeforeDelete、AfterCancel、AfterDelete 等)有效的解决方案?

您必须在赋值时保存旧的 DataSet.AfterOpen 并在 ToBeExecutedOnAfterOpen 中调用保存的方法。 但正如 Abelisto 在他的评论中已经说过的那样,这不是要走的路。它也不会满足您成为 "a solution valid for all events in the datasets" 的要求。也许这对你有帮助:http://delphidabbler.com/tips/194

可以使用虚方法拦截器来拦截DoAfterOpen虚调用

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);

查看此内容了解更多信息 http://docwiki.embarcadero.com/CodeExamples/XE8/en/TVirtualMethodInterceptor_(Delphi)

我假设您可以看到如何扩展它以处理其他情况

您可能会看看面向方面的编程。就像@Jasper 指出的那样...虚拟方法注入...

DSharp 想到轻松设置。看看DSharp.Aspects.Weaver。您可以轻松地绑定到已发布的任何方法或 Public.

-瑞克