我正在编写一个简单的依赖注入/控制反转系统,基于 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 不是做它的名字所表明的事情。