Nested Contexts

Introduction

This tutorial teaches how to nest a context in another context and how injection bindings are passed to nested contexts. As projects get larger and more complex, it is vital to balance the load of complexity over multiple contexts.

This tutorial starts with a fresh new project. If this is the first time using IoC+, we suggest to read the introduction first.

The Logger View

Let’s start with with a simple logger view that will log a message once we hit the space-bar. Create a new script file called “LoggerView.cs” and add the following code.

using IoCPlus;
using UnityEngine;

public class LoggerView : View {

    public readonly Signal LogSignal = new Signal();

    private void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) {
            LogSignal.Dispatch();
        }
    }

}

When hitting the space-bar, it will dispatch its LogSignal. Let’s add a mediator. Create a new script file called “LoggerMediator.cs” and add the following code.

using IoCPlus;
using UnityEngine;

public class LoggerMediator : Mediator<LoggerView> {

    [Inject] string title;

    public override void Initialize() {
        view.LogSignal.AddListener(OnViewLogSignal);
    }

    public override void Dispose() {
        view.LogSignal.RemoveListener(OnViewLogSignal);
    }

    private void OnViewLogSignal() {
        Debug.Log(title);
    }

}

This mediator injects a string, listens to its view’s LogSignal and logs the string on its dispatch. Simple!

The Menu Context

Let’s add a context to bind the string to a value and the mediator to the view. Create a new script file called “MenuContext.cs” and add the following code.

using IoCPlus;

public class MenuContext : Context {

    protected override void SetBindings() {
        base.SetBindings();

        Bind<string>("Menu");

        BindMediator<LoggerMediator, LoggerView>();

        On<EnterContextSignal>().InstantiateView<LoggerView>();
    }

}

The context binds the value “Menu” to the string type, it binds the LoggerMediator to the LoggerView and uses the InstantiateView<T>() method on the EnterContextSignal to easily instantiate the LoggerView in form of a new gameobject.

Let’s create a RootContext for our menu context so we can test our creations. Create a new script file called “MenuRoot.cs” and add the following code.

using IoCPlus;

public class MenuRoot : ContextRoot<MenuContext> { }

Add a new gameobject to the scene and add the MenuRoot component to it. Go ahead and hit play. We should now get the “Menu” message every time we hit the space-bar.

Nesting the Context

Alright, our menu context is all set. Now let’s add a game context that will act as a parent, effectively nesting the menu context. Create a new script file called “GameContext.cs” and add the following code.

using IoCPlus;

public class GameContext : Context {

    protected override void SetBindings() {
        base.SetBindings();

        Bind<string>("Game");

        On<EnterContextSignal>().AddContext<MenuContext>();
    }

}

The game context uses the AddContext<T>() method on the EnterContextSignal to add the menu context as a child.

This instantiates a new menu context. The game context also injects a different value to the string type. All injection and mediator bindings of a parent context are passed to its child contexts. Let’s create a context root for the game context to test our new code. Create a new script file called “GameRoot.cs” and add the following code.

using IoCPlus;

public class GameRoot : ContextRoot<GameContext> { }

Remove the MenuRoot from the empty gameobject in our scene and add the new GameRoot as a new component. Go ahead and hit play!

Overriding Bindings

Notice how the message is still saying “Menu”? This is because the menu context overrides the string injection binding. Let’s remove the string injection binding from the menu context. Open up the MenuContext and update it with the following code.

using IoCPlus;

public class MenuContext : Context {

    protected override void SetBindings() {
        base.SetBindings();

        BindMediator<LoggerMediator, LoggerView>();

        On<EnterContextSignal>().InstantiateView<LoggerView>();
    }

}

There! Go ahead and hit play again. The message should now say “Game”, a value injected via the parent context!

The IoC+ Monitor

Go ahead and open up the IoC+ Monitor.

We see the menu context next to the game context, with an arrow noting that the menu-context is nested.

Conclusion

In this tutorial we’ve seen how to nest a context using the AddContext<T>() method. We used the InstantiateView<T>() method to easily instantiate a view to an new empty gameobject. We also learned that injection and mediator bindings of a parent context are passed to its child contexts, but child context can override them if needed.