创建一个 Delphi IoC。如何禁用 Delphi 的链接器删除未使用的 类
Creating a Delphi IoC. How to disable Delphi's linker from removing unused classes
我在 delphi 中创建了一个 IoC,它能够自动注册任何具有 IocSingletonAttribute 的 classes。
AutoRegister 如下所示。
procedure TIocContainer.AutoRegister;
var
ctx: TRttiContext;
rType: TRttiType;
attr: TCustomAttribute;
&Type: PTypeInfo;
begin
ctx := TRttiContext.Create;
for rType in ctx.GetTypes do
Begin
for attr in rType.GetAttributes do
Begin
if TypeInfo(IocSingletonAttribute) = attr.ClassInfo then
Begin
&Type := IocSingletonAttribute(attr).&Type;
RegisterType(&Type, rType.Handle, True);
End;
End;
End;
end;
然后我创建一个实现并向其添加 IocSingletonAttribute。看起来像这样
[IocSingleton(TypeInfo(IIocSingleton))]
TIocSingleton = class(TInterfacedObject, IIocSingleton)
procedure DoSomeWork;
end;
所以,现在是程序的实际代码。如果我在 IoC 下面编写代码,它就不起作用。 AutoRegister 过程没有选择 TIocSingleton。
var
Ioc: TIocContainer;
Singleton: IIocSingleton;
begin
Ioc := TIocContainer.Create;
try
Ioc.AutoRegister;
Singleton := Ioc.Resolve<IIocSingleton>();
Singleton.DoSomeWork;
finally
Ioc.Free;
end;
end.
但是如果我改写下面的代码,一切都会按预期进行。请注意我是如何声明 TIocSingleton class 并使用它的。
var
Ioc: TIocContainer;
Singleton: IIocSingleton;
ASingleton: TIocSingleton;
begin
Ioc := TIocContainer.Create;
ASingleton := TIocSingleton.Create;
try
Ioc.AutoRegister;
Singleton := Ioc.Resolve<IIocSingleton>();
Singleton.DoSomeWork;
finally
Singleton.Free;
Ioc.Free;
end;
end.
因此,基于此,我假设 Delphi 的编译器链接器正在删除第一个示例中的 TIocSingleton,因为它从未在应用程序的任何部分中明确使用过。所以我的问题是,是否可以针对某个 class 关闭编译器的 'remove unused code' 功能?或者,如果我的问题不是链接器,谁能阐明为什么第二个示例有效但第一个示例无效?
将 {$STRONGLINKTYPES ON}
指令添加到 .dpr。然后应该包括那些类型。但它肯定会炸毁你的应用程序,因为它不适用于单个 class.
感谢 Sebastian Z 的回答和 Agustin Ortu 的评论。他们的回答都让我找到了最终的解决方案。不幸的是,不可能只对一个 class 使用 STRONGLINKTYPES,并且需要以某种方式引用 class。我决定不使用 Augstin Ortu 的确切建议,但我确实使用了这个概念。
在定义 IoC 的单元中,我输出以下空过程。
procedure IocReference(AClass: TClass);
implementation
procedure IocReference(AClass: TClass);
begin
end;
并在 class 中创建一个供 IoC 使用的 class 我添加以下内容
initialization
IocReference(TIocSingleton);
end.
使用过程来防止链接器删除代码而不是仅仅调用 class 函数,例如 (TIocSingleton.ClassName) 的原因是它提供了更好的信息。如果另一个程序员阅读代码,他们可以很好地猜测为什么会有那行代码。
我在 delphi 中创建了一个 IoC,它能够自动注册任何具有 IocSingletonAttribute 的 classes。
AutoRegister 如下所示。
procedure TIocContainer.AutoRegister;
var
ctx: TRttiContext;
rType: TRttiType;
attr: TCustomAttribute;
&Type: PTypeInfo;
begin
ctx := TRttiContext.Create;
for rType in ctx.GetTypes do
Begin
for attr in rType.GetAttributes do
Begin
if TypeInfo(IocSingletonAttribute) = attr.ClassInfo then
Begin
&Type := IocSingletonAttribute(attr).&Type;
RegisterType(&Type, rType.Handle, True);
End;
End;
End;
end;
然后我创建一个实现并向其添加 IocSingletonAttribute。看起来像这样
[IocSingleton(TypeInfo(IIocSingleton))]
TIocSingleton = class(TInterfacedObject, IIocSingleton)
procedure DoSomeWork;
end;
所以,现在是程序的实际代码。如果我在 IoC 下面编写代码,它就不起作用。 AutoRegister 过程没有选择 TIocSingleton。
var
Ioc: TIocContainer;
Singleton: IIocSingleton;
begin
Ioc := TIocContainer.Create;
try
Ioc.AutoRegister;
Singleton := Ioc.Resolve<IIocSingleton>();
Singleton.DoSomeWork;
finally
Ioc.Free;
end;
end.
但是如果我改写下面的代码,一切都会按预期进行。请注意我是如何声明 TIocSingleton class 并使用它的。
var
Ioc: TIocContainer;
Singleton: IIocSingleton;
ASingleton: TIocSingleton;
begin
Ioc := TIocContainer.Create;
ASingleton := TIocSingleton.Create;
try
Ioc.AutoRegister;
Singleton := Ioc.Resolve<IIocSingleton>();
Singleton.DoSomeWork;
finally
Singleton.Free;
Ioc.Free;
end;
end.
因此,基于此,我假设 Delphi 的编译器链接器正在删除第一个示例中的 TIocSingleton,因为它从未在应用程序的任何部分中明确使用过。所以我的问题是,是否可以针对某个 class 关闭编译器的 'remove unused code' 功能?或者,如果我的问题不是链接器,谁能阐明为什么第二个示例有效但第一个示例无效?
将 {$STRONGLINKTYPES ON}
指令添加到 .dpr。然后应该包括那些类型。但它肯定会炸毁你的应用程序,因为它不适用于单个 class.
感谢 Sebastian Z 的回答和 Agustin Ortu 的评论。他们的回答都让我找到了最终的解决方案。不幸的是,不可能只对一个 class 使用 STRONGLINKTYPES,并且需要以某种方式引用 class。我决定不使用 Augstin Ortu 的确切建议,但我确实使用了这个概念。
在定义 IoC 的单元中,我输出以下空过程。
procedure IocReference(AClass: TClass);
implementation
procedure IocReference(AClass: TClass);
begin
end;
并在 class 中创建一个供 IoC 使用的 class 我添加以下内容
initialization
IocReference(TIocSingleton);
end.
使用过程来防止链接器删除代码而不是仅仅调用 class 函数,例如 (TIocSingleton.ClassName) 的原因是它提供了更好的信息。如果另一个程序员阅读代码,他们可以很好地猜测为什么会有那行代码。