I've created a IoC in delphi with the ability to automatically register any classes that have a IocSingletonAttribute to it.
The AutoRegister looks like the following.
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;
I then create a implementation and add the IocSingletonAttribute to it. It looks like this
[IocSingleton(TypeInfo(IIocSingleton))]
TIocSingleton = class(TInterfacedObject, IIocSingleton)
procedure DoSomeWork;
end;
So, now to the actual code of the program. If I write the code below the IoC doesn't work. The AutoRegister procedure didn't pick up TIocSingleton.
var
Ioc: TIocContainer;
Singleton: IIocSingleton;
begin
Ioc := TIocContainer.Create;
try
Ioc.AutoRegister;
Singleton := Ioc.Resolve<IIocSingleton>();
Singleton.DoSomeWork;
finally
Ioc.Free;
end;
end.
But if I write the code below instead everything works as expected. Notice how i have declared TIocSingleton class and have used it.
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.
So based on this, I'm assuming Delphi's compiler linker is removing TIocSingleton in the first example because it was never explicitly used in any part of the application. So my question is, is it possible to turn of the compiler's 'remove unused code' feature for a certain class ? Or if my problem isn't the linker, can anyone shed light on why the second example works but not the first ?
Add the {$STRONGLINKTYPES ON}
directive to the .dpr. Then those types should be included. But it will definitely blow up your application, as it is not available for a single class.
Thanks to Sebastian Z answer for and for Agustin Ortu comment. Both their responses got me to a final solution. It's not possible to use STRONGLINKTYPES for just one class, unfortunately, and the class needs to be referenced somehow. I decided not to use Augstin Ortu exact suggestion but I did use the concept.
In the unit where IoC is defined I output the following empty procedure.
procedure IocReference(AClass: TClass);
implementation
procedure IocReference(AClass: TClass);
begin
end;
And in the class that creates a class to be used by IoC I add the following
initialization
IocReference(TIocSingleton);
end.
The reason to use a procedure to keep the linker from removing the code instead of just calling a class function, eg (TIocSingleton.ClassName) is that it provided better information. If another programmer reads the code they can take a good guess as to why that line is there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With