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