如何使容器忽略特定类型的`Inject`属性?

时间:2018-11-08 21:21:10

标签: delphi dependency-injection spring4d

首先,设置了一个容器来承载单个实例(AsSingleton)作为合成根。然后将此设置移到另一个容器中,以便从中解析多个单例容器,以供新的合成根使用。另外,单例容器的组合根在方法上使用Inject属性。现在,内部单例容器和外部容器都处理Inject属性。但是,只有负责构造实例的内部单例容器才需要这样做,而不是仅将单例容器的生存期绑定到已解析实例的外部容器。

如何使(外部)容器忽略特定类型的Inject属性?


(简体)示例

unit Example;

interface

uses
  Spring.Container,
  Spring.Container.Common;

type
  TComponentB = class
  end;

  TComponentA = class // a TForm descendant
    [Inject]
    procedure Init(const ComponentB: TComponentB);
  end;

procedure Register(const Container: TContainer);
procedure Run;

implementation

{ TComponentA }

procedure TComponentA.Init(const ComponentB: TComponentB);
begin
  WriteLn('TComponentA.Init');
end;

{ Routines }

procedure Register(const Container: TContainer);
const
  ComponentAContainer = 'ComponentAContainer';
begin
  Container.RegisterType<TContainer>(ComponentAContainer).DelegateTo(
    function : TContainer
    begin
      Result := TContainer.Create;
      Result.RegisterType<TComponentA, TComponentA>.AsSingleton;
      // The inner container invokes `[Inject] TComponentA.Init`.
      // This succeeds as the inner container has `TComponentB`
      // registered.
      // This is the desired mechanism of choice to construct
      // the object graph.
      Result.RegisterType<TComponentB, TComponentB>;
      Result.Build;
    end
  );
  Container.RegisterType<TComponentA>.DelegateTo(
    function : TComponentA
    var
      Temp: TContainer;
    begin
      Temp := Container.Resolve<TContainer>(ComponentAContainer);
      Result := Temp.Resolve<TComponentA>;
    end
  );
  // The outer container invokes `[Inject] TComponentA.Init`, too.
  // This does not succeed as the outer container does not have
  // `TComponentB` registered.
  // In fact, this is not desired anyway, as the inner container
  // already constructed the complete object graph for a `TComponentA`
  // instance.
  // Here only the binding of the lifetimes of Temp and Result are
  // supposed to happen (not shown).
end;

procedure Run;
var
  Container: TContainer;
  ComponentA: TComponentA;
begin
  Container := TContainer.Create;
  Register(Container);
  Container.Build;
  ComponentA := Container.Resolve<TComponentA>;
  ComponentA := Container.Resolve<TComponentA>;
  { ... }
end;

end.

注意:为简单起见,此示例忽略了生命周期管理。另外,内部容器实际上包含多个单例,并且将它们手动连接到对象图中并且不使用容器中的AsSingleton,这是一项繁重的工作。 >

0 个答案:

没有答案