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.
-瑞克
我正在开发 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.
-瑞克