13

リファクタリングに時間がかかり、徐々に行わなければならないレガシーコードに依存性注入を使用する最良の方法を見つけようとしています。古いクラスのほとんどは、さまざまなことを決定するために「親」プロパティを使用し、親プロパティは次のようにコンストラクター引数を介して渡されることがよくありました。

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フレームワークを使用して親オブジェクトを設定するために私が認識していない方法論がいくつかあるのでしょうか?

この質問が、私が達成しようとしていることを明確にしていることを願っています。必要に応じて、より多くの説明/コード例を提供させていただきます。

4

1 に答える 1