1

次の例があります。
Container に既に登録されている Interfaced 変数を渡して解決する簡単な方法はありますか?
または、この機能を使用する別の方法はありますか?


それが私のインターフェースです

    IString = interface
      function Value: string;  
    end;  

    IUser = interface
      function Name: IString;
    end;

    ILogin = interface
      function User: IUser;
      function Password: IString;
    end;

クラスの実装

    TString = class(TInterfacedObject, IString)
    private
      FValue: String;
    public
      constructor Create(const AValue: String);
      function Value: String;
    end;

    TUser = class(TInterfacedObject, IUser)
    private
      FName: IString;
    public
      constructor Create(const AName: IString);
      function Name: IString;
    end;

    TLogin = class(TInterfacedObject, ILogin)
    private
      FUser: IUser;
      FPassword: IString;
    public
      constructor Create(const AUser: IUser; const APassword: IString);
      function User: IUser;
      function Password: IString;
    end;

コンテナへの登録

    GlobalContainer.RegisterType<TString>.Implements<IString>;
    GlobalContainer.RegisterType<TUser>.Implements<IUser>;
    GlobalContainer.RegisterType<TLogin>.Implements<ILogin>;


したがって、これらのインターフェイスを作成する必要がある場合、この方法で呼び出すと、ネストされたパラメーターがコードを複雑にし、読むのが面倒になりました (そして見る)

    GlobalContainer.Resolve<ILogin>([
      TValue.From(
        GlobalContainer.Resolve<IUser>([
          TValue.From(
            GlobalContainer.Resolve<IString>(['UserName'])
          )
        ])
      ),
      TValue.From(
        GlobalContainer.Resolve<IString>(['SuperSecretPassword'])
      )
    ]);
4

2 に答える 2

3

まず第一に、これはService Locator のアンチ パターンに似ています。むしろ、ファクトリを使用する必要があります。

現在の構成では、オブジェクト グラフに関する知識と、2 つの異なる値を同じ型に渡す必要があります。工場は非常に良いものです。

そのため、コンシューマー コードで ctor 呼び出しを解決呼び出しに置き換えるだけでなく (できるだけ避ける必要があります)、ケースに合わせてファクトリを登録できます。

type
  ILoginFactory = interface
    [some guid]
    function CreateLogin(const userName, password: string): ILogin;
  end;

  TLoginFactory = class(TInterfacedObject, ILoginFactory)
    function CreateLogin(const username, password: string): ILogin;
  end;

  function TLoginFactory.CreateLogin(const username, password: string): ILogin;
  begin
    // can also inject the container to the factory and use resolve here - 
    // but doing it the pure DI way for now because the graph to create is simple
    Result := TLogin.Create(
      TUser.Create(
        TString.Create(username)),
      TString.Create(password));
  end;

これILoginFactoryは、現在呼び出しがあるクラスに注入する必要がありGlobalContainer.Resolveます。これは、コンポジション ルートに移動するのにも役立ちます。

于 2016-06-28T09:10:29.707 に答える