gpt4 book ai didi

oop - 在Delphi中,如何在基类及其后代类中启用方法指针属性

转载 作者:行者123 更新时间:2023-12-03 15:24:33 25 4
gpt4 key购买 nike

我想创建一个 TService 后代类,将其用作 Windows 服务实现的基础。在我的基类中,我引入了已发布的 ServiceDescription 属性,并使用 AfterInstall 事件处理程序将此描述写入 Windows 注册表中的适当位置。

请注意,由于 TServer 类(在 Vcl.SvcMgr 中声明)是 TDataModule 后代,为了允许 要在对象检查器中显示 ServiceDescription 属性,必须在设计时包中声明此基类,并使用对 RegisterCustomModule 的调用将其注册到 Delphi。此外,该基类的后代必须由 OTA(开放工具 API)向导或某种代码生成器(.pas 和 .dfm 文件)生成。没问题,我已经整理好了,如果您有兴趣,可以从 Marco Cantu 的书 ( http://www.marcocantu.com/ddh/ddh15/ddh15e.htm ) 中阅读更多相关信息。

我陷入困境的是,我想使用基类中的 AfterInstall 事件处理程序来写入注册表,并使用 AfterUninstall 来删除它,但是我想确保我的后代类也支持 AfterInstallAfterUninstall 事件。

我之前从 Ray Konopka 那里了解到,如果您想重新引入一个属性,则必须在后代类中使用访问器方法。因此,下面的代码段代表了我针对 AfterInstall 事件执行此操作的尝试:

  private
// field to store method pointer for the descendant AfterInstall event handler
FFAfterInstall: TServiceEvent;

protected
function GetAfterInstall: TServiceEvent;
procedure SetAfterInstall( value: TServiceEvent );

published
property AfterInstall: TServiceEvent read GetAfterInstall write SetAfterInstall;

我的重写构造函数将一个方法分配给继承的 AfterInstall 属性:

constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
Self.AfterInstall := CallAfterInstall;

end;

在我的 CallAfterInstall 实现中,在运行代码写入 Windows 注册表后,我测试是否已将方法指针分配给我的本地方法指针字段,如果是,我称之为。它看起来像这样:

procedure TTPMBaseService.CallAfterInstall(Service: TService);
var
Reg: TRegistry;
begin
// Code here to write to the Windows Registry is omitted
// Test if our method pointer field has been written to
if Assigned( FFAfterInstall ) then
FFAfterInstall( Service ); // call the method,

end;

我认为这一切都很有意义,而且我认为它应该有效。然而,我被困在访问器方法上。 Get 访问器方法编译得很好,如下:

function TTPMBaseService.GetAfterInstall: TServiceEvent;
begin
Result := FFAfterInstall;
end;

但是我的 SetAfterInstall 方法引发编译时异常,报告参数不足:

procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent );
begin
if value <> FFAfterInstall then
FFAfterInstall := value;
end;

我不知道在这里做什么。我做了以下更改,它可以编译,但它似乎没有完成这项工作:

procedure TTPMBaseService.SetAfterInstall( value: TServiceEvent);
begin
if @value <> @FFAfterInstall then
@FFAfterInstall := @value;
end;

我有两个问题。首先是,我是否采用正确的方法重新引入事件处理程序,同时确保我的基类及其后代都支持此事件?如果我的逻辑是正确的,那么我的 Setter 访问器方法做错了什么?

最佳答案

Am I taking the correct approach to reintroducing an event handler?

也许是的。由于 TService 类的笨拙设计,您无法重写引发事件的方法。

What am I doing wrong with the Setter accessor method?

问题实际上出在你的构造函数中:

constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
Self.AfterInstall := CallAfterInstall;

end;

其中的注释表明您正在设置继承的事件处理程序,但这不是注释下面的代码的作用。尽管分配给Self.AfterInstall,您还是在设置重新引入的属性的值。这是设置继承属性的方法:

constructor TTPMBaseService.Create(AOwner: TComponent);
begin
inherited;
// Hook-up the AfterInstall event handlers
inherited AfterInstall := CallAfterInstall;

end;

But my SetAfterInstall method raises a compile-time exception, reporting that there are not enough parameters.

准确地说,您在 setter 方法中的 if 语句上遇到语法错误。这只是因为这不是在 Delphi 中比较方法引用的方式。请参阅How to check if two events are pointing to the same procedure in Delphi 。为什么你甚至需要进行这样的比较?您可以安全地忽略它。

关于oop - 在Delphi中,如何在基类及其后代类中启用方法指针属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60385552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com