Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you handle objects created at runtime in conjunction with Dependency Injection frameworks?

I love dependency injection frameworks and how they allow me to request the one object everything starts with. All the wiring is made on the first request for that "master" object. However, there are objects that should be created during runtime, e.g. based on user input. And sometimes those newly created objects should be shared among other objects created by the framework.

My current approach is to have "uninitialized" objects injected by the framework. During runtime I set up the object with setter methods as soon as possible.

What I don't like with this approach is that the setter methods are really invoked only once and should then never be touched again. This prevents me from declaring the fields as final. I don't now how to create the object not before all necessary information is available without losing all the benefits from the DI framework.

I'm new to DI. Are there any good patterns for this?


Example:

// The service is used through out the application
interface Service {
  makeRequest()
}

What I want to do after user typed in credentials:

new ConcreteService(username, password)
// but now I need to inject the concrete servive manually everywhere I need it!

What I'm currently doing:

interface Service {
   makeRequest()
   setCredentials(username, password)
}
// service can be injected by framework, but I don't like setter methods
// that much (and they can pollute the interface)
like image 763
S1lentSt0rm Avatar asked Jul 22 '26 11:07

S1lentSt0rm


1 Answers

Most of my experience with dependency injection is with C# but I believe the concept remains the same no matter what language.

What I understand from the original poster is that he's trying to "persist" information within the dependency injection container in order to retrieve the information at a later time.

The problem with this approach is that, in a multi-threaded scenario, there's the possibility that the dependency that you are using to persist information has its values overwritten by another thread. This can happen because the dependency injection container usually holds a single instance of the object which is returned to you whenever you need it. Therefore, you need to make sure that your design is thread safe.

In my experience, using the dependency injection container to maintain state is bad.

What you register in your dependency injection container are the objects that provide a "service" and that don't maintain any state.

Objects that you use to hold information are usually business objects. These business objects should just be instantiated with "new" (without the dependency injection container), populate them in the usual manner (with setters or initialization method or constructor) and just be passed on as part of the signature of the operations that your services expose.

Note: You can register your dependency as "transient" which would tell the dependency injection container to return a new instance every time you ask for the dependency. This would avoid the need to use the "new" keyword explicitly and give you more control when writing unit tests with a mocking framework.

Hope this helps!

like image 173
TchiYuan Avatar answered Jul 25 '26 04:07

TchiYuan