Search code examples
dependency-injectionglobal-variablesstate

How do you avoid injecting global state when sharing dependencies in DI?


Imagine you inject a single database connection to a handful of service classes. They now share what's essentially a global mutable state. How do DI frameworks deal with this? Do they:

  • Freeze the dependency before injection?
  • Only share immutable objects?
  • Wrap each dependency in a decorator to only provide exactly what's dependent on?

I tried searching for this and am a bit surprised I didn't find much. Feel free to provide links.

Related: https://en.wikipedia.org/wiki/Principle_of_least_privilege


Solution

  • Most DI containers provide the feature of registering a dependency within a Lifetime. For instance in .net core DI you can register a service with three different lifetimes:

    • Singleton: There is only one single instance. All the consumers of that service will use that instance. If one consumer changes the state of that dependency, all the other consumers will see that change.
    • Scoped: There is one instance per scope, where a scope is a web request. If a consumer changes the state of a scoped service, all the other consumers that will run in the same web request will see the change.
    • Transient: Each consumer uses a different instance of the service.

    Always in .net core, the DBContext is (by default) added as a scoped service, this means that in the same web request all the consumers will use the same instance and this is useful when you need to run a transaction across different consumers (or better across different repositories).