2015-12-15 14 views
3

隨着Spring4d,你可以像這樣Spring4d:擁有Owner:TComponent參數的自動工廠?

aContainer.RegisterInstance<TFunc<string, TMyObject>>(function(aName : string):TMyObject 
begin 
    Result := TMyObject.Create(aName); 
end); 

以這種方式註冊自定義的工廠,我會beleive,對於每一個從TComponent,一個誰願意通過業主要麼做繼承依賴

// Registrations 

aContainer.RegisterInstance<TFunc<TComponent, TMyObject>>(function(Owner : TComponent):TMyObject 
begin 
    Result := TMyObject.Create(Owner); 
end); 

// Then in code 

constructor TMyClass.Create(aFctry : TFunc<TComponent, TMyObject>); 
begin 
    fObj := aFctry(Self); 
end; 

或者一個還可以做

aContainer.RegisterType<TMyObject, TMyObject>; 

// In code 

constructor TMyClass.Create(aObj : TMyObject); 
begin 
    fObj := aObj; 
    InsertComponent(aObj); 
end; 

雖然,這是很容易出錯/添加代碼菊st通過主人。有沒有一種內置的方式來獲得一個以TComponent作爲參數的工廠,而無需事先在容器中註冊它?

因爲通常我會用

constructor MyObject.Create(aDep : TFunc<TMyDep>); 

沒有註冊TFunc<TMyDep>依賴,但只有TMyDep類型。

它有可能通過類似

constructor MyObject.Create(aDep : TFunc<TComponent, TMyDep>); 

而不必在容器註冊了嗎?

回答

0

據我所知,這是不可能的,沒有註冊。

但是,有一種方法可以使用Spring.Container.Common的不同IFactory<T,TResult>接口來取消1-4參數的手動工廠實現,該接口在註冊時將由DI容器自動執行。

所以,你會登記,像這樣:

aContainer.RegisterType<TMyObject>; 
aContainer.RegisterType<IFactory<TComponent, TMyObject>>.AsFactory; 

註冊的工廠就是這樣,不需要在你身邊的實現 - 容器會解決它。

這意味着,無論何時您需要TMyObject的實例,您都不會直接從容器請求它(從容器中)。相反,您需要請求IFactory<TComponent, TMyObject>的實例,其中TComponentTMyObject構造函數接受的唯一參數。

與從其它類TSomeClass(其中TSomeClass也是一個TComponent後裔)構造函數注入使用情況的例子看起來會像下面這樣:

constructor TSomeClass.Create(const AMyObjectFactory: IFactory<TComponent, TMyObject>); 
begin 
    fMyObjectInstance := AMyObjectFactory(Self); 
end; 

至少對於我來說,這讓事情變得更加簡單。

0

如果我理解正確的話,你儘量避免常規代碼那樣:

aContainer.RegisterInstance<TFunc<TComponent, TMyFirstObject>>(function(Owner : TComponent):TMyFirstObject 
begin 
    Result := TMyFirstObject.Create(Owner); 
end); 

aContainer.RegisterInstance<TFunc<TComponent, TMySecondObject>>(function(Owner : TComponent):TMySecondObject 
begin 
    Result := TMySecondObject.Create(Owner); 
end); 

aContainer.RegisterInstance<TFunc<TComponent, TMyThirdObject>>(function(Owner : TComponent):TMyThirdObject 
begin 
    Result := TMyThirdObject.Create(Owner); 
end); 

好了,你可以定義程序RegisterComponentDescendant,這會爲您創建的面料輔助類,所以代碼你寫遺囑如下所示:

aContainer.RegisterComponentDescendant<TMyFirstObject>; 
aContainer.RegisterComponentDescendant<TMySecondObject>; 
aContainer.RegisterComponentDescendant<TMyThirdObject>; 

並且與以前一樣。 Helper類的定義是這樣的:

TContainerHelper = class helper for TContainer 
    public 
    procedure RegisterComponentDescendant<TMyObject: TComponent>; 
    end; 

及其實施:

procedure TContainerHelper.RegisterComponentDescendant <TMyObject>; 
begin 
    self.RegisterInstance<TFunc<TComponent, TMyObject>>(
    function(Owner : TComponent):TMyObject 
    begin 
     Result := TMyObject.Create(Owner); 
    end); 
end; 
+0

謝謝你們,但更我讀的答案,更多的我問自己,如果生命週期管理(所有權這種情況下)應該注射? – Ludo

+0

@Ludo我們無法瞭解您正在實施的是什麼,所以無法爲您提供有關終身管理的建議。在Delphi中有很多可能性:只通過接口引用訪問你的對象,如果refcount爲零則銷燬它,或者創建層次結構,所有者負責創建和銷燬其組件,或者使其像VCL中那樣,表單擁有所有組件,或者在某些地方有手動內存管理。沒有通用的解決方案。 –