在 Spring4D 中如何解析所有 IFactory,从容器中提供一个参数?

In Spring4D how to ResolveAll IFactory, supplying an argument from the container?

我想调用 GlobalContainer.ResolveAll<IFactory<TBob,IItem>> 来 return 我是一个 IFactories 数组,当它与一个 TBob 一起提供时 return 我是一个 IItem。

我已将 IItems 注册为

  GlobalContainer.RegisterType<IItem,TA>('A');
  GlobalContainer.RegisterType<IItem,TB>('B');

但我找不到注册单个 IFactories 的方法,例如

  GlobalContainer.RegisterType<IFactory<TBob,IItem>('AFac',['A']);
  GlobalContainer.RegisterType<IFactory<TBob,IItem>('BFac',['B']);

因为没有指定 'injected' 值的选项。

我能找到的唯一方法是为每个工厂使用如下代码,但我确信必须有更简洁的方法。 在下面的代码中我发现我必须使用 TFunc 而不是 IFactory 因为它们实际上都是 TFunc 我得到一个 AV.
此外,通过执行此方法,如果 IItem 的构造函数中有任何其他参数,我必须用 [Inject] 标记构造函数,否则解析器将选择继承的构造函数。

  GlobalContainer.RegisterType<TFunc<TBob,IItem>>('AFac').DelegateTo(
    function: TFunc<TBob,IItem>
    begin
      Result:=function(Bob: TBob): IItem
      begin
        Result:=GlobalContainer.Resolve<IItem>('A',[Bob]);
      end;
    end
  );

工厂是通过 RegisterFactory 注册的,它们只支持带有 methodinfo 的接口($M+ 或从 IInvokable 继承)或启用了 methodinfo 的匿名方法类型,例如 Func<...>(推荐)来自 Spring.pas(在 2.0 中引入)(不是来自 SysUtils.pas 的 TFunc<...>)。那是因为它使用参数info来动态构建工厂代码。

你没有明确说明,但我假设 TATB 的构造函数看起来都是这样的:

constructor Create(bob: TBob);

然后你像这样注册它们(请记住,当所有代码都在一个简单的测试 dpr 中时,这可能不起作用,因为当它们在 dpr 中时会出现一些类型信息故障) - 在容器中注册的类型需要在一个单位。

GlobalContainer.RegisterType<IItem, TA>('A');
GlobalContainer.RegisterType<IItem, TB>('B');
GlobalContainer.RegisterFactory<Func<TBob,IItem>>('AFactory', 'A', TParamResolution.ByType);
GlobalContainer.RegisterFactory<Func<TBob,IItem>>('BFactory', 'B', TParamResolution.ByType);
GlobalContainer.Build;
var factories := Globalcontainer.ResolveAll<Func<TBob,IItem>>;
for var factory in factories do
begin
  var item := factory(nil);
  Writeln((item as TObject).ClassName);
end;

这将打印:

TA
TB