我想调用 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
);
发布评论
评论(1)
工厂通过
RegisterFactory
注册,并且仅支持带有 methodinfo($M+
或从IInvokable
继承)的接口或启用了 methodinfo 的匿名方法类型例如 Spring.pas(2.0 中引入)中的Func<...>
(推荐)(而不是来自 Spring.pas 的TFunc<...>
SysUtils.pas)。这是因为它使用参数信息来动态构建工厂代码。您没有明确说明这一点,但我假设 TA 和 TB 的构造函数都如下所示:
然后您像这样注册它们(请记住,当所有代码都在一个简单的测试 dpr 中,因为它们在 dpr 内时会出现一些类型信息故障) - 在容器中注册的类型需要位于一个单元中。
这将打印:
Factories are registered via
RegisterFactory
and they only support interfaces with methodinfo ($M+
or inherited fromIInvokable
) or anonymous method type that have the methodinfo enabled such asFunc<...>
(recommended) from Spring.pas (introduced in 2.0) (notTFunc<...>
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
andTB
both look like this: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.
This will print: