I'm working with the Dependency Injection Pattern in Unity3D (an engine which uses MonoBehavior, a class that doesn't have a constructor, as the base class for all of its game components), and I ended up building my own solution for it. I don't think that, aside from having to write some boilerplate, it's an anti pattern (specially with the few solutions around the system).
I would like to hears cons and alternative solution to my system as I'm still refining it.
Take into consideration that I'm building this system to be easy to use, scalable (up to a certain level, it doesn't have to be a solution to every problem) and it must work with MonoBehaviours
.
My system works the following way:
- You have a single instance of an interface which contains all the dependencies for the whole applicatio. Let's call this
IEverything
- Each class that needs DI will either inherit from a base class (
DependencyInjectionComponent
) or use an interface and apply the subscription by themselves. - On the Awake method all the classes will subscribe/inform the injector and will have the
IEverything
instance injected (same instance for every class). - The class must manually extract the dependencies it needs.
To represent it with code it would be something like this:
public interface IEverything
{
ILogger Logger { get; }
IAnalytics Analytics { get; }
IOtherServices OtherServices { get; }
}
public class MyMonobehaviourWhichDoesNotHaveAConstructor : DependencyInjectionComponent
{
private ILogger logger;
// abstract method in the base class
public void Inject(IEverything everything)
{
logger = everything.Logger;
}
}
As you can see, the implementation only needs one object, so it disregards the rest.
Now, ideally, if I could use constructors I would make it like this:
public class NormalClass
{
private readonly ILogger logger;
public NormalClass(ILogger logger)
{
this.logger = logger;
}
}
But I'm afraid I can't.
Another option is to use a library like Zenject which allows to do something like this:
public class NormalMonoBehaviour : MonoBehaviour
{
[InjectableTag] private ILogger logger;
}
The problem with Zenject is that it can be slow because, with several components, it takes some time to inject the dependencies. "Some time" means that they won't be available in the Awake
method but they will be available on the Start
.
Is there any way I could improve my system or any big issue it has?
From what I analysed, the two biggest problems I found are:
- It requires inheritance or to use an interface
- It injects a big object (although, by sharing the reference there shouldn't be any memory problem)