-
-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When registering services, also register Func<T> and Lazy<T> for services #49
Labels
enhancement
New feature or request
Comments
kzu
added a commit
that referenced
this issue
Dec 13, 2022
Two patterns are quite typical when doing DI: lazy retrieval and factory-style retrieval (which might or might not return same instance, depending on dependency registration). There's a place for both, so this adds support for both. The reasoning for making both registrations transient is that the lifetime of the underlying service is already determined by the implementation registration itself. Both Lazy and Func just delegate to the service provider at invocation time. This simplifies the potential cognitive overhead in understanding what happens for each. If callers cache the Lazy<T>, they'd get single-time retrieval, regardless of the lifetime of the T (that is, the lifetime of the the lazy-initialized T is now tied to the dependency owner at that point. At the same time, the Func<T> will either return a new T on each invocation or not, depending on how the T was registered. This might complicate things if T is disposable, since at that point the caller would need to know not to dispose retrieved instances inadvertently (since the container itself would do so at the right time). So such a dependency is generally advised for non-disposable services (or otherwise transient ones that can be safely disposed after each use via the Func<T>). Closes #49
kzu
added a commit
that referenced
this issue
Dec 13, 2022
Two patterns are quite typical when doing DI: lazy retrieval and factory-style retrieval (which might or might not return same instance, depending on dependency registration). There's a place for both, so this adds support for both. The reasoning for making both registrations transient is that the lifetime of the underlying service is already determined by the implementation registration itself. Both Lazy and Func just delegate to the service provider at invocation time. This simplifies the potential cognitive overhead in understanding what happens for each. If callers cache the Lazy<T>, they'd get single-time retrieval, regardless of the lifetime of the T (that is, the lifetime of the the lazy-initialized T is now tied to the dependency owner at that point. At the same time, the Func<T> will either return a new T on each invocation or not, depending on how the T was registered. This might complicate things if T is disposable, since at that point the caller would need to know not to dispose retrieved instances inadvertently (since the container itself would do so at the right time). So such a dependency is generally advised for non-disposable services (or otherwise transient ones that can be safely disposed after each use via the Func<T>). Closes #49
kzu
added a commit
that referenced
this issue
Dec 13, 2022
Two patterns are quite typical when doing DI: lazy retrieval and factory-style retrieval (which might or might not return same instance, depending on dependency registration). There's a place for both, so this adds support for both. The reasoning for making both registrations transient is that the lifetime of the underlying service is already determined by the implementation registration itself. Both Lazy and Func just delegate to the service provider at invocation time. This simplifies the potential cognitive overhead in understanding what happens for each. If callers cache the Lazy<T>, they'd get single-time retrieval, regardless of the lifetime of the T (that is, the lifetime of the the lazy-initialized T is now tied to the dependency owner at that point. At the same time, the Func<T> will either return a new T on each invocation or not, depending on how the T was registered. This might complicate things if T is disposable, since at that point the caller would need to know not to dispose retrieved instances inadvertently (since the container itself would do so at the right time). So such a dependency is generally advised for non-disposable services (or otherwise transient ones that can be safely disposed after each use via the Func<T>). Closes #49
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The
Microsoft.Extensions.DependencyInjection
does not provide any implicitway of exposing a factory-like
Func<TService>
so that dependencies can beresolved "lazily" but preserving whatever lifecycle was configured for the service.
This is slightly different than a
Lazy<T>
since the lazy will (by definition) beinitialized/retrieved only once, irrespective of the lifetime configured for the
service (i.e. if the resolving component is a singleton, it will "promote" the
dependency to a singleton too since it will be resolved only once too).
It would be nice if the attributed services supported both patterns natively.
The text was updated successfully, but these errors were encountered: