delphi linker inversion-of-control

Creando un IoC Delphi. Cómo deshabilitar el enlazador de Delphi para eliminar clases no utilizadas



linker inversion-of-control (2)

Agregue la directiva {$STRONGLINKTYPES ON} al .dpr. Entonces esos tipos deberían ser incluidos. Pero definitivamente hará volar tu aplicación, ya que no está disponible para una sola clase.

Creé un IoC en Delphi con la capacidad de registrar automáticamente cualquier clase que tenga un IocSingletonAttribute.

El registro automático se parece a lo siguiente.

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;

Luego creo una implementación y agrego IocSingletonAttribute a ella. Se parece a esto

[IocSingleton(TypeInfo(IIocSingleton))] TIocSingleton = class(TInterfacedObject, IIocSingleton) procedure DoSomeWork; end;

Entonces, ahora al código real del programa. Si escribo el código a continuación, el IoC no funciona. El procedimiento AutoRegister no recogió TIocSingleton.

var Ioc: TIocContainer; Singleton: IIocSingleton; begin Ioc := TIocContainer.Create; try Ioc.AutoRegister; Singleton := Ioc.Resolve<IIocSingleton>(); Singleton.DoSomeWork; finally Ioc.Free; end; end.

Pero si escribo el código a continuación, todo funciona como se espera. Observe cómo he declarado la clase TIocSingleton y lo he usado.

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.

Por lo tanto, basado en esto, supongo que el enlazador de compilador de Delphi está eliminando TIocSingleton en el primer ejemplo porque nunca fue utilizado explícitamente en ninguna parte de la aplicación. Entonces mi pregunta es, ¿es posible cambiar la característica del ''eliminar código no utilizado'' del compilador para una cierta clase? O si mi problema no es el enlazador, ¿alguien puede arrojar luz sobre por qué funciona el segundo ejemplo pero no el primero?


Gracias a Sebastián Z responde por y para Agustín Ortu comenta. Ambas respuestas me llevaron a una solución final. No es posible utilizar STRONGLINKTYPES para una sola clase, desafortunadamente, y la clase debe ser referenciada de alguna manera. Decidí no utilizar la sugerencia exacta de Augstin Ortu pero usé el concepto.

En la unidad donde IoC está definido, publico el siguiente procedimiento vacío.

procedure IocReference(AClass: TClass); implementation procedure IocReference(AClass: TClass); begin end;

Y en la clase que crea una clase para ser utilizada por IoC agrego lo siguiente

initialization IocReference(TIocSingleton); end.

La razón para usar un procedimiento para evitar que el vinculador elimine el código en lugar de simplemente llamar a una función de clase, por ejemplo (TIocSingleton.ClassName) es que proporciona una mejor información. Si otro programador lee el código, pueden adivinar por qué esa línea está allí.