Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong when Transient injected to Singleton?

There is a problem of not correctly configured DI containers named Captive Dependency by Mark Seemann. It's obviously, for example, when a "PerCall" dependency is injected into a "Singleton" one. But what about a scenario when "Transient" is injected into "Singleton"? It’s not so obvious to me why I shouldn’t do that especial for some scenarios like a timer registered as transient injected into a singleton service and lives there forever.

There is Lifestyle Mismatches diagnostic warning in SimpleInjector DI container. The description says:

it is safe for a transient component to depend on a singleton, but not the other way around

Why is it bad? A good example of bad things in this case will be extremely useful. Is there any limitation when it "always" bad or some scenarios can be allowed (see my example above)?

like image 733
hcp Avatar asked May 24 '19 09:05

hcp


People also ask

Can you inject transient into singleton?

As long as your Transient component is stateless and as long as that component contains no stateful dependencies, there is no harm in injecting it into a singleton (or scoped) consumer.

Can singleton consume transient?

You should almost never consume scoped service or transient service from a singleton. You should also avoid consuming transient service from a scoped service.

When would you use a transient scoped singleton?

Use Transient lifetime for the lightweight service with little or no state. Scoped services service is the better option when you want to maintain state within a request. Singletons are created only once and not destroyed until the end of the Application. Any memory leaks in these services will build up over time.

What is transient injection?

Transient: In transient, new object instances will be injected in a single request and response. Below is a snapshot image where I displayed GUID values. Scoped: In scoped, the same object instance will be injected in a single request and response.


2 Answers

It's not safe because your transient instance will be forever inside singleton.

Example: you can inject singleton into some another class instance. In that case you will indirectly inject transient instance too. So you can face with thread-safety problems for instance.

If you register class as a singleton you consider it as a thread-safe because you can use the same instance concurrently in few threads. If you register class as transient most likely it's a lightweight and not thread-safe class. That's why you registered it as transient not as singleton, right? And that's why you see warnings: it's not safe to use transient objects concurrently. In asp.net core embedded IoC you will face runtime exception in such case.

Imagine: your transient class creates SqlConnection inside and keeps it opened during its lifetime and allows to use it without synchronization. And that's OK because it's considered to be alive for a short period of time in one thread. Then you inject it into singleton and then you use this singleton in each request.

like image 120
mtkachenko Avatar answered Nov 11 '22 21:11

mtkachenko


It depends on how you define what "Transient" means. The Simple Injector documentation, for instance, states:

Simple Injector considers Transient registrations to be lasting for only a short time; temporary, i.e. short lived and not reused. For that reason, Simple Injector prevents the injection of Transient components into Singleton consumers as they are expected to be longer lived, which would otherwise result in Lifestyle Mismatches.

But other DI Containers use a different definition for "Transient." The .NET Core DI Container (MS.DI), for instance, advises your transient registrations to be "lightweight, stateless services."

As they are assumed stateless, it is safe to inject them into consumers with any other lifetime, as long as they don’t have any stateful (sub) dependencies of their own. “Stateful,” in the context of MS.DI, typically means a scoped dependency. MS.DI's definition of transient is identical to what Autofac calls Instance Per Dependency. IMO, Autofac's naming is more correct, because conceptually, there is a big difference between the two definitions of transient, and I believe most DI Containers follow the "lasting for only a short time; temporary" definition.

As long as your Transient component is stateless and as long as that component contains no stateful dependencies, there is no harm in injecting it into a singleton (or scoped) consumer. Injecting such stateless component into a singleton, however, still makes that component long lived, which is something completely different than being short lived. As Simple Injector doesn't know whether or not your component contains state, it considers all transients to be short lived and, therefore, warns you about injecting transients into singletons.

like image 41
Steven Avatar answered Nov 11 '22 20:11

Steven