例如,我有 3 個這樣的幀:
TBaseFrame = class(TFrame)
end;
TfraDataAwareEntity = class(TBaseFrame )
private
FEntity: TObject;
procedure SetEntity(const Value: TObject);
{ Private declarations }
public
constructor Create(AOwner: TComponent;
ADataset: IDataset;
AEntity: TObject);
property Entity: TObject read FEntity write SetEntity;
end;
TfraDataAwareEntityWithGrid = class(TBaseFrame )
private
FEntity: TObject;
procedure SetEntity(const Value: TObject);
{ Private declarations }
public
constructor Create(AOwner: TComponent;
ADataset: IDataset;
AEntity: TObject);
property Entity: TObject read FEntity write SetEntity;
end;
界面:
IDataset = interface
['{065771AA-A114-4D01-B180-427A39DD51D7}']
procedure Save;
procedure Load;
end;
執行:
TCustomDataset = class(TInterfacedObject, IDataset)
procedure Save;
procedure Load;
end;
登記:
GlobalContainer.RegisterType<TBaseFrame , TfraDataAwareEntity >
('TfraDataAwareEntity ');
GlobalContainer.RegisterType<TBaseFrame , TfraDataAwareEntityWithGrid >
('TfraDataAwareEntityWithGrid ');
GlobalContainer.RegisterType<TCustomDataset >.Implements<IDataset>.AsDefault;
現在我想創建一個框架:
GlobalContainer.Resolve<TBaseFrame>('TfraDataAwareEntity ',
[ Self,
GlobalContainer.Resolve<IDataset>,
SomeObj ]);
上面代碼的問題是,它不接受介面作為引數(錯誤:沒有可以使用這些引數呼叫的 'TContainer.Resolve<FrameUnit.TfraDataAwareEntity >' 的多載版本),我需要傳遞 TCustomDataset 但是如果我有一個回傳 IDataSet 的工廠,我不能使用它,并且我不希望該單元與 TCustomDataset 耦合,而只是 IDataSet。那么我該怎么做呢?
我嘗試的另一個選項是在 TfraDataAwareEntity 建構式上注入 TCustomDataset (例如:使用 Spring4D 進行建構式注入時的“Unsatisfied constructor”)但是我得到一個無法決議 TComponent 的錯誤,有沒有辦法在建構式中的 IDataset 中注入 TCustomDataset 和還傳遞其余引數?
uj5u.com熱心網友回復:
您需要將值包裝成TValue.From(...)(您可以省略 <..> 中的特定型別,因為型別推斷會處理它),因為
- TValue 中沒有采用介面的隱式多載,因此公認的誤導性編譯器錯誤
- Self 和 SomeObj 的隱式多載可能會導致非精確型別,這將導致建構式查找失敗。
我還建議您將其注冊為容器中的工廠函式,以免您在消費者代碼中發布代碼 - 這不是依賴注入,而是服務定位器的反模式,因為您除了使用決議呼叫交換建構式呼叫之外什么也沒得到。
您發布的缺少的代碼:
type
TFrameFactory = reference to function(const AFrameName: string; AOwner: TComponent; AEntity: TObject): TBaseFrame;
GlobalContainer.RegisterInstance<TFrameFactory>(
function(const AFrameName: string; AOwner: TComponent; AEntity: TObject): TBaseFrame
begin
Result := GlobalContainer.Resolve<TBaseFrame>(AFrameName,
[TValue.From(AOwner), TValue.From(GlobalContainer.Resolve<IDataset>), TValue.From(AEntity)]);
end);
然后,您可以將其TFrameFactory注入到您希望能夠構建框架的組件中。
關于春季未來計劃的注意事項:
- 支持部分注入 - 這意味著當不顯式傳遞引數值時,容器知道如何自行決議(例如
IDataset),它將由容器自動決議,從而避免顯式決議呼叫以提供所有引數。 - 支持元資訊 - 目前您只能通過名稱來識別已注冊的服務,這可能有點麻煩。此功能將允許通過列舉之類的東西來識別它們。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/516720.html
