We have an ASP.NET MVC app using IoC to inject Service references into controllers and Repository references into Services.
Controllers have to have a Lifetime of Transient as they must be instantiated per request. If the whole IoC stack is being newed-up per request, though, this gets to be a bit of overhead. We have more dependencies than I'd like, and one option would be to have more controllers, each with fewer dependencies in the stack. But, leaving that aside for now, my question is, if an object that is injected as a singleton has dependencies that have a transient lifetime, will those dependencies essentially be treated like singletons by virtue of being owned by the Singleton?
Specifically, if we have the following
RepositoryA (needs to be transient because current design injects a user context in constructor) ServiceA (singleton) ControllerA (transient)
instantiated like so:
public ServiceA(IRepositoryA repo) {}
public ControllerA(IServiceA service) {}
Will RepositoryA essentially be instantiated once because ServiceA is instantiated once?
I'm 99% sure the answer is yes, but just wanted to confirm the amount of refactoring I have to do here.
Also, assuming Services and Repositories did NOT have any user/request-specific instance variables, as a design approach, is there any reason not to use a Singleton lifetime for them?
if an object that is injected as a singleton has dependencies that have a transient lifetime, will those dependencies essentially be treated like singletons by virtue of being owned by the Singleton?
That's correct. Since such component holds on to its dependencies (by storing their reference in a private field), those dependencies will live as long as the component itself does. In other word, their lifetime is implicitly promoted to the lifetime of the component (if their lifetime is shorter).
If you have this, your DI configuration is most certainly wrong and sooner or later this bug will show up. Probably only in production and hardly ever on your dev machine :-S.
In general all components managed by the container should only depend on abstractions that have a lifespan that is equal or longer than that of the component itself.
Some frameworks even have analysis services in place to detect these kinds of configuration errors. Nonetheless, you should be very careful when wiring up all dependencies. In general it would be safest to configure components as transient whenever possible, since a transient components is allowed to contain dependencies of any lifestyle. Having many transient objects would normally not be a performance problem. Building a rather large object graph per web request would typically be fast enough (otherwise try switching to a DI framework with a higher throughput).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With