2012-07-03 82 views
7

我剛剛開始使用Delphi Spring Framework,並想知道當前版本的DI容器是否允許將構造委派給工廠方法而不指定實現類型?德爾福春天DI:是否有可能委託接口實例沒有實現類型?

E.g.類似的東西:

GlobalContainer 
    .RegisterFactory<ISomeObject>(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .Implements<ISomeObject> // could probably be implied from the above 
    .AsSingletonPerThread; 

正如你所看到的,我的具體用例是COM對象的實例化。在這種情況下,實現我感興趣的接口的類不是我的應用程序的一部分,但我仍然可以通過調用CreateComObject/CoCreateInstance來創建實例。然而,看起來我運氣不佳,因爲Container中的註冊似乎總是綁定到實際的實施類。

假設目前這種情況不可能,那麼專家如何解決這個問題呢?你會創建一個包裝類還是虛擬類,還是隻是簡單地將COM對象從DI容器中取出,並通過CreateComObject來實例化它們?

回答

8

不幸的是,目前的彈簧DI容器設計不允許這樣做。它內部假設每個服務類型(通常是接口,但也可以是一個類)都是由組件類型(一個類)實現的。因此在這種情況下我們需要IInterface的幾個地方有TObject。與傳遞給DelegateTo方法的委託一樣,它將返回組件類型(或非通用情況下的TObject),而不是服務類型。

這也是因爲您可以在一個流暢的接口調用中註冊一個具有多個接口實現的組件類型。像:

GlobalContainer 
    .RegisterType<TMyObject> 
    .Implements<IMyInterface> 
    .Implements<IMyOtherInterface>; 

現在容器檢查,如果TMyObjectIMyInterfaceIMyOtherInterface兼容。當調用Resolve時,服務解析器使用實例上的GetInterface來獲取請求的接口引用。除此之外的所有事情都是在對象引用上完成的。

因爲我有一些DI容器的計劃,在註冊接口時不需要依賴實現類,所以這個問題將在未來得到解決,但不會很快。

更新(2012年8月11日):

由於R522有可能以下列方式進行註冊的接口類型:

GlobalContainer 
    .RegisterType<ISomeObject> 
    .DelegateTo(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .AsSingletonPerThread; 

在本例中,將寄存器ISomeObject作爲服務和任何接口用它繼承的GUID。

此外,您可以通過調用Implements<T>來添加其他接口,但與類不同的是,如果構造的實例實際上確實支持該接口,那麼在註冊時不會有驗證,因爲它根本不可能。當您撥打Resolve<T>時,目前您將獲得nil以及不受支持的服務類型。它可能會在未來引發一個例外。

+3

感謝您的更新!太精彩了! :) –

1

看起來像春天框架的架構目前支持它,但它的確是可行的。在spring4d支持小組中已經有suggested了,這個想法很有趣。

Spring.DesignPatterns中有一個通用TFactory類,可能用於包裝CreateComObject/COCreateInstance