Search Unity

Dependency Injection, MonoBehaviours and Constructors

Discussion in 'Scripting' started by Tseng, May 4, 2015.

  1. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    I had a look at a few of the "so called" DI frameworks for Unity3D and to be honest, I don't like any of them.

    I've been working for years with Unity IoC Container and I am pretty proficient with it, but all of the Unity3D IoC Containers are far off from traditional IoC Containers.

    One of the most annoying things is that most of them require a scene object with their Context/Installer stuff, ultimately leading to a few issues, like

    No clean way to implicitly resolve the Dependencies, i.e. having to call ".Inject()" inside Start (which is far too late in some cases)
    Creating a base class for MonoBehaviours becomes a pain (either forcing to override Start/Awake or creating another method to call it and not touching Start/Awake at all in dereived classes
    Probably most annoying: Very Inspector heavy configuration.

    Under the one I considered so far: Zenject, StrangeIoC, Adic.

    So I was playing with the idea of of simply scrapping all of that and using Unity and using the MonoBehaviour constructor to resolve all non-MonoBehaviour dependencies. We all know, blah blah, don't use constructors in MonoBehaviours.

    The main reason for it is, cause the MonoBehaviour get instantated, deserialized and then attached to the game object so any changes there (to the properties/fields) would be overwritten by the deserialization and of course all the C++-wrapper methods/properties won't be accessible during the constructor (like .enable, .transform etc.).

    But aside that, I don't see anything that would prevent doing dependency resolving within the constructor, if the dependencies aren't derived from MonoBehaviour (which I don't intend to do).

    Something along the lines of for all MonoBehaviour derived scripts

    Code (CSharp):
    1.  
    2. public DiBehaviour : MonoBehaviour
    3. {
    4.     public DiBehaviour()
    5.     {
    6.         // MonoBehaviour Extension Method
    7.         this.Inject();
    8.     }
    9. }
    10.  
    11. public static void Inject(this MonoBehaviour monoBehaviour)
    12. {
    13.     // Get lazy configured container
    14.     var container = UnityBootstrapper.GetConfiguredContainer();
    15.     container.BuildUp(monoBehaviour);
    16. }

    This would keep the derived classes free of "having to remember" to call ".Inject()" within Awake/Start methods, would be IoC container agnostic and we could have all dependencies we need/configured when Awake() is called and even Objects not having a Awake/Start Method, would have their non-MonoBehaviour dependencies injected.

    And most importantly, no need for some stupid in scene game objects which you have to wait and make sure they were initialized by Unity3D before you can use it.

    Now the real question is: What downside we can expect using the above behaviour, except not be able to inject MonoBehaviour derived classes via it (which I don't inted to)?

    Is there something with the editor that may mess up with it? The above constructor will always be parameterless, so Editor should be able to instantiate it w/o any issues.
     
    Ben-BearFish likes this.
  2. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    I've never used IoC in Unity, but I'd be interested in the responses you receive as I'd like to do what you're trying at some point.