首先,设置了一个容器来承载单个实例(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
,这是一项繁重的工作。 >