The Unity Game Engine uses the Open Source .NET platform (Mono), which means you can use existing .NET code written in C#. In this article, I will explain how to use Autofac with Unity so that you can minimize coupling and increase testability.
There are many IoC containers to choose from when developing .NET applications. The container I use is Autofac because it works for .NET and Mono. I prefer it because it allows me to use the same container for ASP.NET MVC, SignalR, WPF and Unity without having to learn a different API.
Unfortunately the latest version of Autofac can't be used with Unity because it uses portable class libraries that are .NET Framework 4 and above. If you want to use Autofac with Unity, you will need version 2.5.2.830 which is based on .NET Framework 3.5.
DependencyResolver
class for service location from MonoBehavior
scripts.Bootstrap
class that derives from MonoBehavior
.Bootstrap
class to an empty GameObject in your scene.Bootstrap
script first.The DependencyResolver
class provides a way of globally accessing the Autofac container anywhere in your Unity project. The purpose of this class is so that we can use the service locator pattern to resolve dependencies from the IoC container.
using System; using UnityEngine; using Autofac; public class DependencyResolver { public static IContainer Container {get; set;} }
Note. I know its considered an anti-pattern and bad practice to use the service locator pattern but in Unity we have no choice. This is because there are no extension points in the API that allow us to inject dependencies into
MonoBehaviour
classes.
The Bootstrap
class is responsible for wiring up the dependencies when the game first launches so that they can be resolved from MonoBehavior
scripts. Below is an example Bootstrap class that wires up an example ILogger
.
using UnityEngine; using System.Collections; using Autofac; public class Bootstrapper : MonoBehaviour { void Awake () { var builder = new ContainerBuilder(); builder.RegisterType<Logger>().As<ILogger>(); DependencyResolver.Container = builder.Build(); } }
The call to DependencyResolver.Container = builder.Build();
is required at the end of the set-up because it makes the container available to any script.
TIP: Check out the Autofac documentation on how to automatically register dependencies based on namespaces or naming conventions.
The following CharacterController
script shows how you would resolve an ILogger
instance.
using UnityEngine; using System.Collections; using Autofac; public class CharacterController : MonoBehaviour { public ILogger Logger {get; set;}; // Use this for initialization void Start () { Logger = DependencyResolver.Container.Resolve<ILogger>(); Logger.Log("Started Character Controller Script"); } }
Although the service locator has been used for MonoBehaviour
scripts to resolve dependencies in the Start
or Awake
methods. I would recommend using constructor injection for anything that is not a MonoBehavior
class. The reason why the service locator has been used is because constructor injection is not possible with Unity MonoBehaviour
classes.
This example is a very basic introduction on how to use the Autofac IoC container with the Unity game engine. If you are currently using dependency injection and unit testing, you might find it useful to add an injection framework like Autofac to your project.