2014-03-31 63 views
4

我在Spring4D框架中很新,並請求幫助。如何在Spring4d中從ServiceLocator獲取子接口實例?

我旁邊的類和接口:

ICommand = interface 

TCommand = class(TInterfacedObject, ICommand) 

IVecadCommand = interface(ICommand) 

TVecadCommand = class(TCommand, IVecadCommand) 

TVecadCommandJPG = class(TVecadCommand, IVecadCommand) 

TCommandDeckelJPG = class(TVecadCommandJPG, IVecadCommand) 

然後我註冊一個組件:

GlobalContainer.RegisterComponent<TCommandDeckelJPG>.Implements<IVecadCommand>('deckel_jpg'); 

然後我嘗試與服務定位器的幫助下創建一個對象:

var 
    i: Integer; 
    com: ICommand; 
begin 
    Result := nil; 
    com := ServiceLocator.GetService<ICommand>(actionName); 
    com.setSession(designSession); 
    Result := com; 
end; 

作爲執行的結果,我有一個例外:

Invalid class typecast 

爲了避免例外,我賺那麼:

var 
    i: Integer; 
    com: IVecadCommand; 
begin 
    Result := nil; 
    com := ServiceLocator.GetService<IVecadCommand>(actionName); 
    com.setSession(designSession); 
    Result := com; 
end; 

那麼一切都OK。

一點是我一直用它TContainer在這種情況下,存儲庫TCommand和繼承類。所以我必須首先使用ServiceLocator。

我應該怎麼做,以避免異常和使用的ICommand但TContainer不IVecadCommand?

謝謝。將提供額外的細節與樂趣。

回答

6

您註冊IVecadCommand但要求ICommand

的錯誤是誤導性的,實際上它應該提出一個異常告訴你,它不知道如何解決(似乎是一個錯誤 - 我會考慮這一點)。

這是因爲您只能要求明確註冊的服務。它沒有查找繼承鏈。

如果您希望能夠將您的課程也解析爲ICommand,則需要在註冊中添加另一個.Implements<ICommand>。由於名稱必須是唯一的,您可能想要按名稱解析,因此必須給它一個與IVecadCommand不同的名稱。如果你從來不去解決它作爲IVecadCommand(你可以使用支持,一旦你作爲ICommand解決),那麼只需要改變現有註冊從IVecadCommandICommand

編輯: 我其實並不完全正確 - 當你通過名稱解析容器不檢查傳遞的類型。在這種情況下,問題是將IVecadCommand轉換爲ICommand,由TValue.AsType<T>完成。但它沒有正確處理。我將在即將到來的版本中修復這個問題。我只是不知道如何。爲了保持一致性,這裏也應該嚴格限定類型。無論如何,如果你按照上面提到的解決問題,現在你是安全的。

更新2014年4月10日: 我已經做了修復這個問題所以現在應該可以做一個名爲決心找回瞭解決一個的父接口。

+0

是的,我找到了相同的解決方案。非常感謝。 – mad

相關問題