HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Dependency Injection Provider/Container

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
injectioncontainerproviderdependency

Problem

I've been working on a class to handle dependency injection across some code akin to a micro-framework. This is also my first real dive into any sort of wrapper for dependency injection. I decided to write a pseudo-intelligent dependency provider that recursively constructs dependencies. I also included the ability to share objects, which seems to put it somewhere between design patterns.

The most abstract feature is the recursion in make(), where it uses reflection classes to automatically inject dependencies into the dependency it's currently creating.

I've got a couple of questions:

-
My first question is whether or not this would be considered a "container" or a "registry" - Initially I named it a "provider" to stay close to literal meaning, but it seems most like a container to me. The class turned out to have components of a few design patterns (not exactly what i intended, but it's working), but I'm not looking to invent a mashup of design patterns...

-
Secondly (and more importantly), the shared object pool is dancing on a fine line with the global state, which I want to avoid. So far only a few classes get put into this pool, namely the input handler class, which handles superglobal interactions. Is there a more sophisticated way to ensure the same object is injected for certain classes, or is almost-global-state the only way to go?

Recursively injecting dependencies has been great so far, cutting out a lot of code by eliminating the need to even recognize those dependencies. However it has caused some roadblocks along the way, where constructor parameters are limited to namespaced objects. I am slightly worried that this sort of requirement could cause major problems down the road, so I'm all ears for words of advice.

Finally, the code:

```
_reflectionContainer = $reflectionContainer;
}

/**
* Called to inject a dependency - will either pull an object out of the shared
* pool, or create a new object. Sub-dependencies are resol

Solution


  • It depends on how you use it. Your "sharedObjects" part would probably fit Registry pattern if you start using it as global object. On the other hand usually Registry does not create objects, but rather store them. Your implementation is a proper container as long as you don't start passing it around or start using it globally (that would make it "Service locator" pattern).



  • I wouldn't call that global state. I assume you need that to make sure your object gets instantiated only once. The way I used to do it in my C++ implementation of container is store a map of factories in it. That factory could be any kind of a "callable" function (lambda expression, pointer to function, functor, etc..) and it was wrapped in a "ICreationStrategy" interface. If I needed to create object only once - I used SingletonCreationStrategy which worked exactly the same way as Singleton design pattern does, but without using static variable. This way you can store object instance in CreationStrategy instead of container directly (although I don't really see a problem with storing it the way you did).



I'll write an example when I'm gonna have more time.

Context

StackExchange Code Review Q#15527, answer score: 3

Revisions (0)

No revisions yet.