Closed AliveDevil closed 8 months ago
That's interesting. Am I right the proposal implies:
IMethodBasedFactory
- an interface you can extendIServiceCollection.AddMethodBasedFactory<TFactory>() where TFactory: IMethodBasedFactory
, which resolves to a proxy acting as you've described. I.e. it automatically wires up any method call on it to an implementation, which create the actual object relying on ActivatorUtilities.CreateFactory
& method call arguments.And ultimately, it allows to replace untyped ~ services.Activate(...)
calls with typed ~ myFactory.CreateSomething(...)
, + also boost the performance of such calls due to activator/factory caching?
I'd also add proxy support for that, btw - i.e. auto-replacement of a type with Stl.Interception
proxy, if it's available for that type (coz most likely that's the expected outcome in such cases).
@AliveDevil I like the idea - it feels handy, + moreover, if the "default" construction helper won't fit some specific case, you can always add extension methods to the interface for custom construction.
If you have some time, please send this PR - I'll definitely accept it, though might make some changes afterwards :)
And I'll be happy to do this anyway at some point (not sure when yet) - I like the proposal.
P.S. Great you dug pretty far into that - this part is almost undocumented.
I like IMethodBasedFactory
- sounds good.
Adding MethodBasedActivatorUtilitiesInterceptor
for this as the interception proxy (using the ActivatorUtilities factory).
Does Stl have any support of dynamic proxies (not generated through Stl.Generation
)? Otherwise making IMethodBasedFactoryDefaultProxy
could be a challenge (or I'm missing something here).
P.S. Great you dug pretty far into that
If there's no documentation, I'm really stubborn and dig into everything until I have a solution. Not the best habit in terms of time-efficiency, but for some personal project it works out fine.
[…] boost the performance of such calls due to activator/factory caching?
I'd not want to vouch for that, though it makes it way more type-safe and improves discoverability - the factory caching does make it faster, as there is just the initial discovery phase of the constructor, then the factory delegate performs a regular constructor call.
The ObjectFactory itself is using params object[]
internally, so whether that makes any difference I'm not sure about - as all value types are boxed again.
I mean, there is the option of porting back ActivatorUtilities^1 to not rely on object[] args
, but that may overshoot the goal by miles.
You are free to edit the PR, it’s „allow edit for maintainers“ enabled.
I'd like to know whether there is any better way of creating a Factory, that intercepts methods calls on that interface for passing these on to ActivatorUtilities, or if there is interest in this being integrated into Stl.Interception as a native supported pattern:
Registering a factory:
The interface is to make sure, that Stl.Generated-proxies are found correctly, and are available for consumption - this could probably be reduced to
AddFactory<T> () where T : IRequiresAsyncProxy
, but for me I implemented it this way for now.And eventually could be used for something like:
which returns an instance of
Regarding
ArgumentList.ToArray()
is probably not the best way to go about it (ObjectFactory is defined asdelegate object? ObjectFactory(IServiceProvider, params object[] args)
, but I didn't see any other way as I figuredArgumentList.GetInvoker()
isn't going to cut it, as it won't create the params-array when called.