0

I ran into the problem of binding components from a child component, a solution to this problem is possible?

At the moment I have a solution, but it is inconvenient, you need to forward all methods through 1 component. Example:

public inteface ITextView
{
   void SetText(string text);
}

public ButtonView : Monobehaviour, ITextView
{
   [SerializedField] private Text _text;

   public void SetText(string text)
   {
      _text.text = text;
   }
}

public SomeWindow : Monobehaviour, IButtonView
{
   [SerializedField] private TextView _textView;

   public void SetText(string text) => _textView.SetText(text);
}

In this case, with the growth of inherited interfaces, the forwarding of methods grows. As a possible solution to the problem, it is also possible to simply create an interface that stores references to all dependencies. Example:

public interface ISomeWindowFacade
{
   ITextView TextView { get; }
   //Some dependence
   //Another one
}

But in this case, I will pass unnecessary dependencies to most classes

Is it possible to store links to the required dependencies in SomeWindow and bind the rest after its creation?

public Installer : ScriptableObjectInstaller
{
   [SerializedField] private SomeWindow _window;

   public override void InstallBindings()
   {
      Container.BindInterfacesTo<ISomeWindowFacade>.FromComponentInNewPrefab(_window).AsSingle();
   }
}

1 Answers1

0

Perhaps I did not state the problem correctly, but here's the gist. There is a SOInstaller that stores a link to the prefab, at the time of the bind I created an instance of this component and wanted to receive the component itself and its children as separate components. I found solutions to this problem:

  1. The implementation of the component must store the MonoBehaviour list, you can make an abstract class that stores a link to the list
    public interface IWindowView{}
    public ConcreteWindow : MonoBehaviour, IWindowView
    {
       [SerializedField] private List<MonoBehaviour> _children;
       public List<MonoBehavior> Children => _children;
    }
  1. In the installer (as in my case in SOInstaller) we add a link to the prefab with the component and instantiate the component and bind it
    public class SomeInstaller : ScriptableObjectInstaller
    {
       [SerializeField] private ConcreteWindow _window;
    
       public override InstallBindings()
       {
          //If you use an abstract class, you can convert to it
          var window = Container.InstatiatePrefabForComponent<ConcreteWindow>(_window);
          Container.BindInterfacesTo(window.GetType()).AsSingle();
       }
    }
  1. Now we can go through all the child elements, inject them and bind
public class SomeInstaller : ScriptableObjectInstaller
{
    [SerializeField] private ConcreteWindow _window;
    public override InstallBindings()
    {
       //Previous
          foreach(var component in window.Children)
          {
             Container.Inject(component);
             Container.BindInterfacesTo(component.GetType()).AsSingle();
          }  
    }
}

As a result, we get the following, we have created an object that stores the components and can receive them separately in the desired class

public class SomeClass
{
   //ISomeView - child implementer
   public SomeClass(IWindowView windowView, ISomeView someView)
   {
   }
}