2017-02-05 45 views
6

Utworzono IoC w delphi z możliwością automatycznego rejestrowania dowolnych klas, które mają do niego IocSingletonAttribute.Tworzenie IoC Delphi. Jak wyłączyć linker Delphi z usuwania nieużywanych klas?

AutoRegister wygląda następująco.

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; 

Następnie tworzę implementację i dodaję do niej IocSingletonAttribute. Wygląda teraz tak, jak na aktualny kod programu. Jeśli piszę poniższy kod, IoC nie działa. Procedura AutoRegister nie pobrała TIocSingleton.

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

Ale jeśli napiszę poniższy kod, wszystko działa zgodnie z oczekiwaniami. Zwróć uwagę, jak zadeklarowałem klasę TIocSingleton i użyłem jej.

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. 

więc na podstawie tego, jestem przy założeniu Delphi kompilator łącznik usuwania TIocSingleton w pierwszym przykładzie, ponieważ nigdy nie został wyraźnie stosowane w dowolnej części aplikacji. Moje pytanie brzmi: czy możliwe jest wyłączenie funkcji "usuń nieużywany kod" kompilatora dla danej klasy? Lub jeśli moim problemem nie jest linker, czy ktoś może rzucić światło na to, dlaczego drugi przykład działa, ale nie pierwszy?

+3

Myślę, że jedyną nadzieją jest dołączenie kodu, który zmusza łącznika do włączenia klasy. Dodanie inicjalizacji TIoCSingleton.ClassName zrobi. Tak, musisz to zrobić dla każdej klasy, w której się rejestrujesz. Inną możliwością może być użycie pakietów –

+0

Dzięki za napiwek. Wywołanie TIoCSingleton.ClassName w części inicjalizacyjnej jednostki może nie być zbyt trudne, aby żyć z – Coolio

Odpowiedz

1

Podziękowania dla Sebastiana Z za odpowiedź i za komentarz Agustina Ortu. Obie odpowiedzi doprowadziły mnie do ostatecznego rozwiązania. Niemożliwe jest użycie STRONGLINKTYPES tylko dla jednej klasy, a do klasy należy się odwoływać. Postanowiłem nie wykorzystywać dokładnej sugestii Augstin Ortu, ale użyłem tej koncepcji.

W jednostce, w której zdefiniowano IoC, wyprowadzam następującą pustą procedurę.

procedure IocReference(AClass: TClass); 

implementation 

procedure IocReference(AClass: TClass); 
begin 
end; 

A w klasie, która tworzy klasę być wykorzystywane przez IoC dodam następujące

initialization 
    IocReference(TIocSingleton); 
end. 

powód do korzystania z procedury, aby utrzymać łącznik z wyjęciem kod zamiast po prostu wywoływania Funkcja klasy, np. (TIocSingleton.ClassName), zapewnia lepszą informację. Jeśli inny programista odczyta kod, może zgadnąć, dlaczego ta linia jest.

3

Dodaj dyrektywę {$STRONGLINKTYPES ON} do .dpr. Następnie należy uwzględnić te typy. Ale z pewnością wysadzi w powietrze twoją aplikację, ponieważ nie jest dostępna dla jednej klasy.

+0

Czy na pewno to zadziała? Większość dyrektyw kompilujących należy dodać do opcji kompilatora (-> plik .dproj) lub do poszczególnych jednostek, aby uzyskać jakikolwiek efekt. – dummzeuch

+0

Poprawiam się: "Aby działać niezawodnie, dyrektywa powinna znajdować się w głównym programie lub źródle biblioteki (.dpr)." "http://docwiki.embarcadero.com/RADStudio/en/Strong_link_types_(Delphi) – dummzeuch