8

作成時点から渡されることが期待されるパラメータを持つクラスを登録することは可能ですか?

私はそれが次のようなことができることを知っています:

GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>.
AsTransient.DelegateTo(
    function: TUserProcessor
    begin
      Result := TUserProcessor.Create(GetCurrentUser);
    end
  );

ただし、パラメーターは、オブジェクトがインスタンス化される場所ではなく、コンテナーが登録される実行コンテキストにバインドされます。

たとえば、このようなことは可能ですか?

GlobalContainer.Resolve<IMathService>([FCurrentUser]);

非常に単純なコンストラクターを使用することを支持する人々を知っていますが、コンストラクターのパラメーターが明らかに適切に見える場合があります。

  1. 構築されたオブジェクトが機能するには object パラメーターが必要であるため、参照が満たされている必要があります。また、このパラメーターは、その制約をクラスで見るとより明確にします。

  2. 最初に割り当てを行わずにオブジェクトを使用しようとすると、メソッドまたはプロパティで参照を割り当て、他のすべてのメソッドで発生させて例外を発生させることができます..私はこのタイプのコードを書くのは好きではありません.コンストラクターパラメーターを使用して、そこで確認してください。コードが少ないほど、IMO は向上します。

  3. また、渡されるオブジェクトは、コンテナーを使用して新しいオブジェクトを構築するオブジェクト (たとえば、Transaction オブジェクト) に対してローカルであり、何らかの状態を持っています (コンテナーで取得できる新しいオブジェクトではありません)。

4

2 に答える 2

7

Unity のようにリゾルバーのオーバーライドを追加しました。

したがって、次のように書くことができます。

program Demo;

{$APPTYPE CONSOLE}

uses
  Classes,
  Spring.Container,
  Spring.Container.Resolvers;

type
  IUserUpgrader = interface
    ['{ADC36759-6E40-417D-B6F7-5DCADF8B9C07}']
  end;

  TUser = class(TObject);

  TUserProcessor = class(TInterfacedObject, IUserUpgrader)
  public
    constructor Create(AUser: TUser);
  end;

constructor TUserProcessor.Create(AUser: TUser);
begin
  Writeln('called constructor with passed user');
end;

begin
  GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>;
  GlobalContainer.Build;

  GlobalContainer.Resolve<IUserUpgrader>(
    TOrderedParametersOverride.Create([TUser.Create]));

  GlobalContainer.Resolve<IUserUpgrader>(
    TParameterOverride.Create('AUser', TUser.Create));

  Readln;
end.

編集 17.09.2018:

これはかなり前に変更され、Resolve は を介し​​てパラメーターを受け入れますarray of TValue。そこに直接値を渡すこともできます。これは、ctor のパラメーター リストと正確に一致する必要があります。使用できるパラメータを部分的にのみ入力する場合TNamedValue、またはTTypedValueSpring.pas から

とにかく、工場を使用してコードによって注入および消費され、コンテナー (グローバルなものであろうとなかろうと) Resolve メソッドに到達しないことをお勧めします。

于 2012-05-23T12:59:18.337 に答える
0

次のスレッドをご覧ください: https://forums.embarcadero.com/message.jspa?messageID=440741

フレームワークでこれを実装し、コードで使用しています。ご希望でしたら、お送りします。これは、コードベースにこのような機能を追加する場合に行われる方法ではないことに注意してください。Baoquan には私のコードがあります。

この実装は、必要なすべてのパラメーターなしで解決しようとした場合にも処理し、欠落しているパラメーターを示す例外を提供します。

次のように使用します。

ServiceLocator.GetService<ISomeObj>(ServiceParameters['paramname1',value1]['paramname2',value2]..);

値は TValue として保存され、何でもかまいません。

パラメータをクラスに登録するには、次のような属性を使用します。

private
  [ContainerParameter('paramname1')]
  FYourValue1: ...;
  [ContainerParameter('paramname2')]
  FYourValue2: ..;

あなたもできる

[ContainerParameter]
FYourValue1:.. 

ただし、パラメーターの名前は「FYourValue1」です。

于 2012-05-06T12:13:39.847 に答える