The Dynamic Abstract Factory is so useful but it's like magic to me!

255 views
Skip to first unread message

Edwin Yip

unread,
Jun 30, 2017, 5:20:21 AM6/30/17
to Spring4D
So I've just started using DI and spring4d since a few days ago. 

And I learned that the consumer classes should not aware of the DI container. But what if the consumer class needs to create service instances dynamically? For example, to create new service instances for each new thread?

I figured out I should resort to the Factory pattern, on which the consumer classes can depend and ask it to create new service instances for them.

So I search all across the Internet for Spring4D related staff, using keywords such as 'IFactory', 'AsFacory', 'TFunc<...>', And so on, finally I land on the DynamicAbstractFactory example. Bingo! That's exactly what I wanted and my initial experiment showed that it works.

After knowing how to do it I then trying to figure out why it works, but unfortunately that example has no comment and I couldn't find any info.

So I guess the Spring4D framework creates the so-called dynamic proxies for implementing the 'Abstract Factories'. Am I right? I guess so.

And here comes the real question - Is there any limit on the number of parameters the constructor of the class being made by the factory? Thanks. 

Honza Rameš

unread,
Jul 3, 2017, 9:08:41 AM7/3/17
to Spring4D
Hi Edwin,
yes factory interfaces are implemented by creating TVirtualInterface at runtime which implement any interface that has enough RTTI available so that the system knows enough information about how the calls are actually made and how arguments are transferred (this is why the interface needs to inherit from IInvokable or has to be placed inside {$M+}...{$M-}).

There are some (system/Delphi) limits when it comes to what argument types you can pass (which depends on compiler version you use), best practice is to write a test for your factory and see if it works (in case you suspect any issues). As for the number of arguments, I don't think there is any limitation. However you may notice some conflict in how your arguments are passed around which is where TParamResolution enumeration comes in. The objects returned by the factory are returned in the same way as if you call Container.Resolve with arguments, the containers tries to match the arguments you passed in with whatever constructor of the target type and tries to resolve any further dependencies (if need, you don't need to pass all arguments required by the constructor to the factory method, the container will figure out the dependencies itself but make sure to register everything properly).

I hope I described it clearly enough for you to understand and didn't made it too messy ;-). Stefan may add more insight into the matter but you should have enough information to get you started ...

Honza

PS.: Feel free to ask if you run into problems but please always add MVCE so we can get back to you quickly without trying to figure out how to reproduce the issue while spending precious time that could otherwise be put into new features ;-)

Edwin Yip

unread,
Jul 3, 2017, 9:35:42 AM7/3/17
to Spring4D
Hi Honza,

Thanks for the help! I think I understand you to level that's enough for me as  the user of the framework ;)

Just one thing that's strange - My factory interface is not  declare inside a block, but it still work (I tested and confirmed), why? I'm using XE4.

  IProjectLoader = interface
  ['{824EF995-FB97-47A8-B34D-067D866A252A}']
    function LoadProject(const aPath: String): TWoProject;
  end;

  IProjectLoaderFactory = interface(IInvokable)
  ['{252D41F7-3FE4-78A9-B447-0A217AE16DBB}']
    function Create: IProjectLoader; overload;
  end;


Honza Rameš

unread,
Jul 3, 2017, 10:59:28 AM7/3/17
to Spring4D
I maybe failed to stress that you either have to inherit from IInvokable or place the interface inside the M block. As you can see IInvokable just inherits from IInterface but is placed inside the M block which makes the compiler emit RTTI for it and any sub-interface.

Dne po 3. 7. 2017 15:35 uživatel Edwin Yip <edwi...@innovationgear.com> napsal:
--
You received this message because you are subscribed to the Google Groups "Spring4D" group.
To unsubscribe from this group and stop receiving emails from it, send an email to spring4d+u...@googlegroups.com.
To post to this group, send email to spri...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/spring4d/51491266-9794-4006-bfa9-797712684c96%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Edwin Yip

unread,
Jul 3, 2017, 11:31:55 AM7/3/17
to Spring4D
Thanks Honza, it's all clear now :)
Reply all
Reply to author
Forward
0 new messages