在类构造函数中完成类注册后,不调用类构造函数

2024-04-02

我正在编写一个简单的依赖注入/控制反转系统,基于 TDictionary 保存抽象类引用及其各自的实现类。

我的目标是:

  • 避免按类型直接实例化(显然)。
  • 将类单元包含在 dpr 中应该足以使其注册并可通过 di/ioc 系统进行选择和实例化。
  • 声明具体的实现类执行仅部分。
  • 使用类构造函数而不是初始化部分。

顺便说一句,我知道使用类构造函数来利用智能链接和希望包含一个单元足以使类可用是相互矛盾的。出于其他原因,我想使用类构造函数而不是初始化部分。我想将所有类初始化/注册代码保留在一起,而不必将其拆分在类构造函数和初始化部分之间。

Problem

我希望将类注册到工厂中,并在类构造函数中进行。不幸的是,编译器认为仅在其自己的类构造函数中使用其类型并不会“触及”该类。

当我将注册函数放在初始化部分时,编译器确实认为该类已被触及并调用类​​构造函数。但这违背了我将所有类初始化代码保留在类构造函数中的目的。

两个问题

  • 编译器是否应该考虑在自己的类构造函数中使用该类“接触类”,还是期望编译器这样做太多了?
  • 有人对如何在不使用初始化部分的情况下仍然实现我的目标有任何聪明的想法吗?

Example

应用程序中使用的抽象类:

TSite = class abstract (TObject)
  function GetURL: string; virtual; abstract;
  property URL: string read GetURL;
end;

TSites = class (TList<TSite>);

TThisApplication = class abstract (TObject)
  function Sites: TSites; virtual; abstract;
end;

TThisApplication 的具体实现类(在实现部分声明!)

  TThisApplicationConcrete = class(TThisApplication)
  class constructor ClassCreate;
  strict private
    FSites: TSites;
    function Sites: TSites; override;
  end;

class constructor TThisApplicationConcrete.ClassCreate;
begin
  RegisterImplementorClass(TThisApplication, TThisApplicationConcrete);
end;

function TThisApplicationConcrete.Sites: TSites;
var
  SiteList: TSites;
begin
  if not Assigned(FSites) then begin
    SiteList := TSites.Create;  // Change to use factory
    //RetrieveSites(SiteList);
    FSites := SiteList;
  end;

  Result := FSites;
end;

获取 TThisApplication 实例的函数:

function ThisApplication: TThisApplication;
var
  ImplementorClass: TClass;
begin
  ImplementorClass := GetImplementorClass(TThisApplication);
  if Assigned(ImplementorClass) then begin
    Result := ImplementorClass.Create as TThisApplication;
  end else begin
    Result := nil;
  end;
end;

目前,这是在单独的函数中编码的,但可以将其移至工厂。

完整示例代码

如果有人想进行实验,我可以在以下位置找到我的测试项目的完整代码:http://www.bjsoftware.com/delphistuff/stackoverdlow/classconstructors.zip http://www.bjsoftware.com/delphistuff/stackoverdlow/classconstructors.zip

邮编内容:

  • 4 个项目都使用相同的源文件,仅条件定义不同(这就是 dproj 也包含在内的原因)
  • 4个源文件
  • groupproj 及其包含所有 4 个项目的 DSK
  • RunTestApps.cmd 运行所有 4 个项目
  • Results.txt 包含我运行 RunTestApps.cmd 的输出
  • WriteUp.txt 包含此问题的文本

请记住,您始终需要执行“构建所有项目”,因为所有 dcu 和 exe 都将转到源目录,否则您将面临很多错误和/或混乱,因为 exe 不是做它的名字所表明的事情。


这正如预期的那样。正如 Uwe 指出的,自引用类构造函数不足以触发包含。将引用放在初始化部分就可以解决问题,因为它位于类本身之外。试图自我引用一个类以进行包容就像试图通过拉自己的背带把自己从深坑里拉出来。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在类构造函数中完成类注册后,不调用类构造函数 的相关文章

  • 如何使用 VCL 类的接口 - 第 2 部分 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 继续我之前关于使用 VCL 接口的调
  • 为什么变量被声明为 TStrings 并被创建为 TStringList?

    为什么变量声明为TStrings并创建为TStringList 例如 varsl被声明为TStrings但创建为TStringList var sl TStrings begin sl TStringList Create add stri
  • 如何在以管理员身份运行模式下部署应用程序?

    如何部署应用程序 使其需要管理员权限 而无需最终用户手动执行此操作 我使用 Delphi 2009 来构建该应用程序 您可以使用以下命令通知 Windows 您的应用程序需要以管理员身份运行requestedExecutionLevel应用
  • 使用 gmail 和 Indy 发送电子邮件

    我正在尝试使用 gmail 从 Delphi 发送电子邮件 我有 Indy 10 5 9 0 和 Delphi XE3 我从以下位置获得了示例代码 http www andrecelestino com delphi xe envio de
  • XE2 中的 COM 是否损坏?我该如何解决它?

    Update XE2 Update 2 修复了下述错误 下面的程序是从实际程序中截取的 在 XE2 中失败并出现异常 这是 2010 年的回归 我没有 XE 来测试 但我希望该程序在 XE 上运行良好 感谢 Primo 确认代码在 XE 上
  • 在 Inno Setup 中使用 StringToColor

    我想为表单上的标签 TNewStaticText 属性颜色 TColor 读写 分配一些颜色 我将颜色存储为 RRGGBB 字符串 我想使用 Delphi 函数 StringToColor 将其转换为 TColor 但如果我在脚本中使用此函
  • vcl组合框并不总是显示它有焦点

    当我从另一个控件切换到组合框时 它会显示文本周围带有虚线的框 但是当我以编程方式将控件设置为活动状态时 它不会显示相同的焦点指示器 这种行为有解决方法吗 我有德尔福XE6 MCVE unit Unit27 interface uses Wi
  • delphi定时器比定时器服务中断例程更快

    大家好 我被要求为某人维护一个基于 Delphi 5 的程序 该程序使用一个计时器对象每 50 毫秒计时一次 并且在每次计时结束时运行单线程代码块 我只是想知道 如果执行这段代码所花费的时间比计时器滴答间隔长 会发生什么 这会很糟糕吗 例如
  • 在运行时创建 TQReport 元素

    在运行时创建 TQReport 元素 嗯 至少尝试一下 我不知道这份报告中应出现哪些标题或数据 我得到一个代表数据行和列的 TString 的 TList 我在组的带打印事件中植入 创建 指令 并在主数据行带的 OnNeedData 事件中
  • 如何将我的图标添加到组件选项板页面中的组件? [复制]

    这个问题在这里已经有答案了 可能的重复 Delphi非可视化组件图像 https stackoverflow com questions 3319276 delphi non visual component image 如何将我的图标添加
  • 如何从具有管理员权限的应用程序接收键盘输入到非管理员应用程序?

    我编写了一个应用程序 该应用程序具有覆盖类型的窗口 可以通过热键显示和隐藏该窗口 而另一个应用程序具有焦点 所述另一个应用程序是一个以管理员权限运行的 DirectX 游戏 我已经尝试了 3 种可能的解决方案 以便在其他应用程序中按下我的热
  • 如何仅在调试模式下激活 ReportMemoryLeaksOnShutdown?

    我需要激活ReportMemoryLeaksOnShutdown报告应用程序内存泄漏的功能 但仅限于调试模式 当 Delphi IDE 运行时 我怎样才能做到这一点 如果您的意思是使用调试构建配置 D2007 编译的 调试模式 则您将定义
  • Delphi线程死锁

    我有时会在销毁某些线程时遇到死锁问题 我尝试过调试该问题 但在 IDE 中调试时似乎从未存在死锁 可能是因为 IDE 中的事件速度较低 问题 当应用程序启动时 主线程会创建多个线程 线程始终处于活动状态并与主线程同步 完全没有问题 当应用程
  • 我可以让我的 Delphi 应用程序在特定时间(例如上午 12:00)启动,而不运行应用程序吗?

    我看到一个已安装的应用程序 它从供应商的网站提供一些 XML 数据并将其显示在主窗体窗口中 我想这很简单 但我注意到 即使我关闭系统托盘中的应用程序 明天早上 上午 12 00 正好 它也会再次弹出 这太酷了 我不确定它是用 Delphi
  • 如何在 Delphi REST 中发布内容类型为“multipart/form-data”的数据?

    我正在尝试使用 REST API 发送请求multipart form data作为内容类型 我总是收到 HTTP 1 1 500 Internal Error 作为响应 我尝试向需要的方法发送请求application x www for
  • 运行delphi客户端自动化程序后excel.exe保持加载状态的原因是什么?

    我编写了一个 Delphi 程序 该程序从单个 XLS 文件的多个不同电子表格中提取数据并将其合并到文本文件中以供以后处理 这是德尔福7console程序 最相关的代码片段的摘录将向您表明 显然 我的程序表现得相当好 或者至少达到了它需要的
  • Delphi - 在修复 VCL 错误时,单元 x 是用不同版本的 x 编译的

    我正在使用 Delphi XE6 并在我的项目中使用 Datasnap 和 JSON 我想纠正 VCL 单元 System JSON pas 在 TJSONString ToString 函数中 中的一个错误 它应该转义反斜杠字符和引号 为
  • 如何遍历任意给定集合中的枚举?

    我有很多枚举类型 它们与相应的集合相结合 例如 type TMyEnum meOne meTwo meThree TMyEnums set of TMyEnum 我正在尝试提出一组可以运行的函数any枚举集 而不是为每个枚举编写单独的函数
  • Word 2010 自动化:“转到书签”

    我有一个用 Delphi 7 编写的程序 它打开一个基于模板的新 Word 文档 文档打开后 系统会自动跳转到书签 在模板中预定义 并在其中添加一些文本 以下代码在 Word 2003 中工作正常 但会导致invalid variant o
  • 在 Delphi 中使用 XML(将特定数据返回到变量)

    过去几天我一直在尝试使用 Delphi 2010 和 MSXML 我是一个极端的新手 需要一点指导 var MemoryStream TMemoryStream XMLPath String sName String XMLDoc vari

随机推荐