リファクタリングに時間がかかり、徐々に行わなければならないレガシーコードに依存性注入を使用する最良の方法を見つけようとしています。古いクラスのほとんどは、さまざまなことを決定するために「親」プロパティを使用し、親プロパティは次のようにコンストラクター引数を介して渡されることがよくありました。
constructor TParentObject.Create;
begin
FChildObject := TChildObject.Create(Self);
end;
constructor TChildObject.Create(AParent: TParentObject)
begin
FParent := AParent;
end;
これは、従来のコード ベースの典型的な例です。ただし、インターフェースとコンストラクター注入に移行する場合、子オブジェクトを作成するときに、Spring4D フレームワークは親を認識しません。したがって、既存の親ではなく、新しい親を取得します。もちろん、プロパティのゲッター/セッターを作成することはできますが、これは実際には必須のプロパティであるクラスの「オプションの」プロパティを示します。詳細については、次のコードを参照してください。
unit uInterfaces;
interface
uses
Spring.Collections;
type
IChildObject = interface;
IParentObject = interface
['{8EA8F9A2-E627-4546-8008-0A77DA2B16F1}']
function GetSomethingRequiredByChild: string;
procedure SetSomethingRequiredByChild(const Value: string);
property SomethingRequiredByChild: string read GetSomethingRequiredByChild write SetSomethingRequiredByChild;
function GetChild: IChildObject;
property Child: IChildObject read GetChild;
end;
// This introduces a property getter/setter
// However it also implies that Parent can be NIL which it cannot
IChildObject = interface
['{ECCA09A6-4A52-4BE4-A72E-2801160A9086}']
function GetParent: IParentObject;
procedure SetParent(const Value: IParentObject);
property Parent: IParentObject read GetParent write SetParent;
end;
TParentObject = class(TInterfacedObject, IParentObject)
private
FChild: IChildObject;
FSomethingRequiredByChild: string;
function GetChild: IChildObject;
function GetSomethingRequiredByChild: string;
procedure SetSomethingRequiredByChild(const Value: string);
public
constructor Create;
end;
TChildObject = class(TInterfacedObject, IChildObject)
private
FParent: IParentObject;
function GetParent: IParentObject;
procedure SetParent(const Value: IParentObject);
public
// This requries a Parent object, but how does the Spring4D resolve the correct parent?
constructor Create(const AParent: IParentObject);
end;
implementation
uses
Spring.Services;
{ TParentObject }
constructor TParentObject.Create;
begin
// Here is the old way...
FChild := TChildObject.Create(Self); // Old way of doing it
// This is the Service Locator way...
FChild := ServiceLocator.GetService<IChildObject>;
// I would prefer that the Parent is assigned somehow by the Service Locator
// IS THIS POSSIBLE - or am I dreaming?
FChild.Parent := Self;
end;
function TParentObject.GetChild: IChildObject;
begin
Result := FChild;
end;
function TParentObject.GetSomethingRequiredByChild: string;
begin
Result := FSomethingRequiredByChild;
end;
procedure TParentObject.SetSomethingRequiredByChild(const Value: string);
begin
FSomethingRequiredByChild := Value;
end;
{ TChildObject }
constructor TChildObject.Create(const AParent: IParentObject);
begin
FParent := AParent;
end;
function TChildObject.GetParent: IParentObject;
begin
Result := FParent;
end;
procedure TChildObject.SetParent(const Value: IParentObject);
begin
FParent := Value;
end;
end.
DIフレームワークを使用して親オブジェクトを設定するために私が認識していない方法論がいくつかあるのでしょうか?
この質問が、私が達成しようとしていることを明確にしていることを願っています。必要に応じて、より多くの説明/コード例を提供させていただきます。