Refactor ContextHolder

Issue #10 resolved
Jöran Malek created an issue

I suggest making ContextHolder abstract only providing Get/Set-Access to Context and Type. As well as using an event for ContextChanged-Notifications. Reason: If I have multiple DataContexts that may be relevant for different things in the game I cannot use this because I cannot reference other DataContexts from one GameObject.

public class ContextPointer : ContextHolder
{
    public ContextHolder ContextHolder;

    public override object Context
    {
        get
        {
            return ContextHolder.Context;
        }
        set { }
    }
    public override Type ContextType
    {
        get
        {
            return ContextHolder.ContextType;
        }
        set { }
    }

    protected void OnEnable()
    {
        ContextHolder.ContextChanged += ContextHolder_ContextChanged;
    }
    protected void OnDisable()
    {
        ContextHolder.ContextChanged -= ContextHolder_ContextChanged;
    }

    private void ContextHolder_ContextChanged()
    {
        OnContextChanged();
    }

    protected override void OnContextChanged()
    {
        // Update child bindings as context changed.
        var uiBindings = this.gameObject.GetComponentsInChildren<Setter>(true);
        foreach (var binding in uiBindings)
        {
            binding.OnContextChanged();
        }
        var providers = this.gameObject.GetComponentsInChildren<DataProvider>(true);
        foreach (var provider in providers)
        {
            provider.OnContextChanged();
        }
        var commands = this.gameObject.GetComponentsInChildren<Command>(true);
        foreach (var command in commands)
        {
            command.OnContextChanged();
        }
        base.OnContextChanged();
    }
}

Or, if this is not a practical approach try to make Bindings independent from their parents (i.e. allow Bindings from root\Object1 to root\Object2 where Object1 has the ContextHolder)

Comments (5)

  1. Christian Oeing repo owner

    Hi there!

    Thanks a lot for the suggestion. I will have a detailed look into it, probably at the weekend.

    About multiple contexts: You know that you can have sub contexts in a context? If not, check out the ContextProperty example. For example we create a WindowContext for a UI window we open and reference the context that are available in that window in the WindowContext. So we just need one ContextHolder for the window and the paths are then SubContextA.Object1, SubContextB.Object2,... Let me know if that already solves your problem!

    Cheers Christian

  2. Jöran Malek reporter

    Hi,

    okay ... my setup is like the following:

    /Camera
    /Terrain
    /Canvas/Button
    /EventSystem { With MenuSystem, GameSystem Components }

    Now the EventSystem should be the default ContextHolder for everything and I want to be able to apply this ContextHolder as Reference to the Canvas and Terrain. The reason for this is, that I don't want to apply MenuSystem and GameSystem to every of these Controls, because that's not how I want it to work.

    So the ContextProperty example uses a collection which I won't because I'm generating things on the fly from prefabs that can differ in everything.

  3. Christian Oeing repo owner

    What was of interest in the ContextProperty example is the data property "SelectedItem" in ContextPropertyContext. This is a reference to another data context (a ContextPropertyItemContext in that case).

    The ContextHolder script is meant to be placed above the game objects which have the bindings. So if you use it in your canvas, you should add a ContextHolder to it or have a common parent game object for Canvas and EventSystem. You could also have two ContextHolder which reference the same Context.

    The ContextHolder is really just a helper to make the data context which should be used available for the Unity bindings. Letting the ContextHolder create its context makes only sense for debugging most of the time. Normally you create the context in your code and set it to the ContextHolder where it should be used.

    Hope my explanations make sense :)

  4. Christian Oeing repo owner

    Hi there!

    Just added an event to the ContextHolder when its context changed. Do you still need some changes to the ContextHolder class or have you found a different solution for your structure?

    Cheers Christian

  5. Log in to comment