Delphi - how to pass parameter from instance to constructor in spring4d dependency injection platform?

Is it possible to register a class with a parameter that is expected to be passed from the point of creation?

I know this can be done something like this:

GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>. AsTransient.DelegateTo( function: TUserProcessor begin Result := TUserProcessor.Create(GetCurrentUser); end ); 

But there the parameters are tied to the execution context in which the container is registered, and not where the object is tricked.

Is something like this possible, for example?

 GlobalContainer.Resolve<IMathService>([FCurrentUser]); 

I know that some peoble supporters have very simple constructors, but there are times when the constructor parameter explicitly looks like this:

  • The created object requires that the parameter of the object work, so the link must be executed. The parameter also makes this restriction much more obvious when looking at a class.

  • You can assign a reference in a method or property, and also raise and exclude in every other method if you try to use an object without prior assignment. I don't like writing this type of code, it's just a waste of time, just use the constructor parameter and check there. The less code, the better IMO.

  • Also, the object is passed locally to the object, which creates a new object using the container (for example, the Transaction object) and has some state (this is not a new object that I can get with the container).

+8
dependency-injection delphi delphi-xe2 spring4d
source share
2 answers

I added overrides, as in Unity.

So you can write:

 program Demo; {$APPTYPE CONSOLE} uses Classes, Spring.Container, Spring.Container.Resolvers; type IUserUpgrader = interface ['{ADC36759-6E40-417D-B6F7-5DCADF8B9C07}'] end; TUser = class(TObject); TUserProcessor = class(TInterfacedObject, IUserUpgrader) public constructor Create(AUser: TUser); end; constructor TUserProcessor.Create(AUser: TUser); begin Writeln('called constructor with passed user'); end; begin GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>; GlobalContainer.Build; GlobalContainer.Resolve<IUserUpgrader>( TOrderedParametersOverride.Create([TUser.Create])); GlobalContainer.Resolve<IUserUpgrader>( TParameterOverride.Create('AUser', TUser.Create)); Readln; end. 
+7
source share

You can check this thread: https://forums.embarcadero.com/message.jspa?messageID=440741

I implemented this implementation in my structure and used it in my code. If you want it, I will send it to you. Keep in mind that this is not how it can be done, when and if they add such functions to the code base. Baoquan has my code.

This implementation is also processed if you try to resolve without all the necessary parameters and gives you an exception showing the missing parameters.

You use it as follows:

 ServiceLocator.GetService<ISomeObj>(ServiceParameters['paramname1',value1]['paramname2',value2]..); 

The value is stored as TValue and can be anything.

Registering a parameter with your class is performed using the following attributes:

 private [ContainerParameter('paramname1')] FYourValue1: ...; [ContainerParameter('paramname2')] FYourValue2: ..; 

You can also do

 [ContainerParameter] FYourValue1:.. 

But then your parameter has the name FYourValue1 as the name.

0
source share

All Articles