For an example I would like to resolve a class passing in a TComponent and TNotifyEvent such as below but the base constructor of TObject gets called and not of TMy.
GlobalContainer.RegisterType<TMy>;
GlobalContainer.RegisterFactory<Func<TComponent,TNotifyEvent,TMy>>(TParamResolution.ByType);
var F:=GlobalContainer.Resolve<Func<TComponent,TNotifyEvent,TMy>>;
F(Self,Self.OnActivate);
I can get around the issue by writing some very ugly code as below but think that this kind of resolution would be so common that I must be doing something wrong.
TOther = class
end;
TMy = class
public
constructor Create(C: TComponent; N: TNotifyEvent; O: TOther);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
GlobalContainer.RegisterType<TOther>;
GlobalContainer.RegisterType<TMy>;
GlobalContainer.RegisterType<Func<TComponent,TNotifyEvent,TMy>>(
function: Func<TComponent,TNotifyEvent,TMy>
begin
Result:=Func<TComponent,TNotifyEvent,TMy>(
function(O: TComponent; N: TNotifyEVent): TMy
begin
Result:=TMy.Create(O,N,GlobalContainer.Resolve<TOther>);
end
);
end
);
GlobalContainer.Build;
var F:=GlobalContainer.Resolve<Func<TComponent,TNotifyEvent,TMy>>;
F(Self,Self.OnActivate);
end;
constructor TMy.Create(C: TComponent; N: TNotifyEvent; O: TOther);
begin
OutputDebugString('Resolved');
end;
Thanks in advance for any pointers.
This should work now after the latest commit in develop.
The issue was the typed parameter resolution was bound to the argument type instead of the parameter type. In this case, this resulted in a typed value with type
TForm2
(taken from the argument being passed) which did not match the type of the C argument of the constructor of typeTComponent
because that matching checks for type identity and not assignment compatibility.After the fix typed parameter resolution works exactly on the parameter types of the factory function instead of the possibly (in case of objects) more narrow actual type of the argument.
FWIW for future reference - when registering a factory manually it's usually not necessary to use
RegisterType
providing the delegate but can directly useRegisterInstance
like so (keep in mind thatSpring.Func<...> has
const` parameters) when it does not have any captured state:Edit: I also added automatic detection for the best parameter resolution default. When the factory type is a
Spring.Func<...>
it automatically usesByType
so it can omitted from theRegisterFactory
call. For all other types it usesByName
as default as before.