Dependency injection 如何委派容器1.解决<;T>;至集装箱2.解决<;T>;,如果Container1无法解析T?

Dependency injection 如何委派容器1.解决<;T>;至集装箱2.解决<;T>;,如果Container1无法解析T?,dependency-injection,spring4d,Dependency Injection,Spring4d,使用Spring4D,我想构建一个容器,如果它不能解析服务,则将服务解析委托给另一个容器——大致如下: function TContainer.Resolve<T>: T; begin if not TryResolve<T>(Result) then Result := OtherContainer.Resolve<T>; end; 函数T容器。解析:T; 开始 如果不是TryResolve(结果),则 结果:=其他容器。解析; 结束; 这是

使用Spring4D,我想构建一个容器,如果它不能解析服务,则将服务解析委托给另一个容器——大致如下:

function TContainer.Resolve<T>: T;
begin
  if not TryResolve<T>(Result) then
    Result := OtherContainer.Resolve<T>;
end;
函数T容器。解析:T;
开始
如果不是TryResolve(结果),则
结果:=其他容器。解析;
结束;

这是可能的吗?

在处理特定类型或类型模式的容器中有所谓的子依赖解析程序(未来的版本将称之为类型解析程序)(例如能够解析
TArray
IList
,其中T是正在注册的对象)

您可以实现自己的解决方案,检查类型是否不在您附加此解析器的容器内,然后将此类型的解决链委托给另一个容器

下面是一些示例代码,说明如何实现这一点(无需释放对象)

使用
春天
弹簧,容器,
Spring.Container.Core,
System.SysUtils;
类型
TFoo=类
结束;
TBar=类
私有的
fFoo:TFoo;
公众的
构造函数创建(constfoo:TFoo);
属性Foo:TFoo读取fFoo;
结束;
TSubContainerResolver=类(TInterfacedObject,ISubDependencyResolver)
私有的
f容器:t容器;
fSubContainer:t容器;
公众的
构造函数创建(const容器,子容器:TContainer);
函数CanResolve(const-context:ICreationContext;
常量依赖项:TDependencyModel;常量参数:TValue):布尔;
函数解析(const-context:ICreationContext;
常量依赖项:TDependencyModel;常量参数:TValue):TValue;
结束;
{TBar}
构造函数TBar.Create(const-foo:TFoo);
开始
fFoo:=foo;
结束;
{TSubContainerResolver}
构造函数TSubContainerResolver.Create(常量容器,子容器:TContainer);
开始
F容器:=容器;
fSubContainer:=分包商;
结束;
函数TSubContainerResolver.CanResolve(常量上下文:ICreationContext;
常量依赖项:TDependencyModel;常量参数:TValue):布尔;
开始
结果:=非fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
和fSubContainer.Kernel.Resolver.CanResolve(上下文、依赖项、参数);
结束;
函数TSubContainerResolver.Resolve(常量上下文:ICreationContext;
常量依赖项:TDependencyModel;常量参数:TValue):TValue;
开始
结果:=fSubContainer.Kernel.Resolver.Resolve(上下文、依赖项、参数);
结束;
程序场景一;
变量
c1,c2:t容器;
b:TBar;
开始
c1:=t容器。创建;
c2:=t容器。创建;
c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1,c2));
//子容器中的依赖关系
c1.注册类型;
c1.建造;
c2.注册类型;
c2.建造;
b:=c1。解析;
断言(赋值(b.fFoo));
结束;
程序场景二;
变量
c1,c2:t容器;
b:TBar;
开始
c1:=t容器。创建;
c2:=t容器。创建;
c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1,c2));
c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2,c1));
//在子容器中键入,但在父容器中键入依赖项
c1.注册类型;
c1.建造;
c2.注册类型;
c2.建造;
b:=c1。解析;
断言(赋值(b.fFoo));
结束;
开始
场景一;
情景二;
结束。
uses
  Spring,
  Spring.Container,
  Spring.Container.Core,
  System.SysUtils;

type
  TFoo = class

  end;

  TBar = class
  private
    fFoo: TFoo;
  public
    constructor Create(const foo: TFoo);
    property Foo: TFoo read fFoo;
  end;

  TSubContainerResolver = class(TInterfacedObject, ISubDependencyResolver)
  private
    fContainer: TContainer;
    fSubContainer: TContainer;
  public
    constructor Create(const container, subContainer: TContainer);

    function CanResolve(const context: ICreationContext;
      const dependency: TDependencyModel; const argument: TValue): Boolean;
    function Resolve(const context: ICreationContext;
      const dependency: TDependencyModel; const argument: TValue): TValue;
  end;

{ TBar }

constructor TBar.Create(const foo: TFoo);
begin
  fFoo := foo;
end;

{ TSubContainerResolver }

constructor TSubContainerResolver.Create(const container, subContainer: TContainer);
begin
  fContainer := container;
  fSubContainer := subContainer;
end;

function TSubContainerResolver.CanResolve(const context: ICreationContext;
  const dependency: TDependencyModel; const argument: TValue): Boolean;
begin
  Result := not fContainer.Kernel.Registry.HasService(dependency.TypeInfo)
    and fSubContainer.Kernel.Resolver.CanResolve(context, dependency, argument);
end;

function TSubContainerResolver.Resolve(const context: ICreationContext;
  const dependency: TDependencyModel; const argument: TValue): TValue;
begin
  Result := fSubContainer.Kernel.Resolver.Resolve(context, dependency, argument);
end;

procedure ScenarioOne;
var
  c1, c2: TContainer;
  b: TBar;
begin
  c1 := TContainer.Create;
  c2 := TContainer.Create;
  c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));

  // dependency in subcontainer
  c1.RegisterType<TBar>;
  c1.Build;
  c2.RegisterType<TFoo>;
  c2.Build;

  b := c1.Resolve<TBar>;
  Assert(Assigned(b.fFoo));
end;

procedure ScenarioTwo; 
var
  c1, c2: TContainer;
  b: TBar;
begin
  c1 := TContainer.Create;
  c2 := TContainer.Create;

  c1.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c1, c2));
  c2.Kernel.Resolver.AddSubResolver(TSubContainerResolver.Create(c2, c1));

  // type in subcontainer but dependency in parent container
  c1.RegisterType<TFoo>;
  c1.Build;
  c2.RegisterType<TBar>;
  c2.Build;

  b := c1.Resolve<TBar>;
  Assert(Assigned(b.fFoo));
end;

begin
  ScenarioOne;
  ScenarioTwo;
end.