在Spring4D中如何ResolveAll IFactory,从容器提供参数?

发布于 2025-01-15 05:24:07 字数 1001 浏览 0 评论 0 原文

我想调用 GlobalContainer.ResolveAll> 来返回一个 IFactories 数组,当提供 TBob 时,该数组会返回一个 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']);

没有指定“注入”值的选项。

我能找到的唯一方法是为每个工厂提供如下代码,但我确信必须有一种更干净的方法。 在下面的代码中,我发现我必须使用 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
  );

I would like to call GlobalContainer.ResolveAll<IFactory<TBob,IItem>> to return me an array of IFactories which when supplied with a TBob with return me an IItem.

I have the IItems registered as

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

But I can't find a way to register the individual IFactories such as

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

as there is not an option to specify the 'injected' values.

The only way I can find to do it is to have code like below for each factory but am sure there must be a cleaner way.
In the following code I have found I have to use TFunc and not IFactory as although they both are in fact TFunc I get an AV.
Also by doing this method I have to mark the constructor with [Inject] if there are any other parameters in the IItem's constructor otherwise the resolver picks the inherited constructor.

  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
  );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽袖吟 2025-01-22 05:24:07

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

您没有明确说明这一点,但我假设 TA 和 TB 的构造函数都如下所示:

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

Factories are registered via RegisterFactory and they only support interfaces with methodinfo ($M+ or inherited from IInvokable) or anonymous method type that have the methodinfo enabled such as Func<...> (recommended) from Spring.pas (introduced in 2.0) (not TFunc<...> from SysUtils.pas). That is because it uses the parameter info to dynamically build the factory code.

You did not explicitly stated that but I assume the constructors of TA and TB both look like this:

constructor Create(bob: TBob);

You then register them like this (keep in mind that this might not work when all code is in a simple test dpr because of some typeinfo glitches when they are inside the dpr) - the types being registered in the container need to be in a unit.

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;

This will print:

TA
TB
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文