Skip to content

Add OnCompleted overrideable TempleteMethod and suppress "Warning When Resolving During Install" #296

@BrayanKhosravian

Description

@BrayanKhosravian

Is your feature request related to a problem? Please describe.
Following scenario:

  1. Player (and other GameObjects) is/are in the Hierarchy
  2. Installer is in the scene
  3. public field of type GameObject is in the installer
  4. field is set through the Hierarchy windows
  5. in InstallBindings Container.Inject(Player) is called
  6. warning is displayed "Warning When Resolving During Install"

As some GameObjects have to be located in the Hierarchy window,
I do not know a better way to handle this scenario.
Maybe integrate this case into this framework?

Describe the solution you'd like
Add a protected virtual Method OnInstalled acting as a template method.
This method gets called when the installation is being finished.
Suppress the warning "Warning When Resolving During Install" internally.
Clients can "Inject" the GameObjects in the template method.
The template method is being internally called y the framework.
Maybe add a warning to not Register inside the template method?

Describe alternatives you've considered
A client could still disable the warning.
But it would be cleaner to handle this case.

Additional context

public class TestInstaller : MonoInstallerBase
{
    [InjectGameObject]
    public GameObject PlayerObject;

    protected override void RegisterServices(DiContainer container)
    {
        Container.Bind<IEventManager>().To<EventManager>().AsSingle().NonLazy();




        //Container.Inject(PlayerObject);
    }
}

internal class InjectGameObjectAttribute : HeaderAttribute
{
    // This attribute can be used to mark fields that should be injected by Zenject.
    // It can be used in conjunction with MonoInstaller or other Zenject installation methods.
    public InjectGameObjectAttribute() : base("GameObject references")
    {
    }
}

internal class  InjectPrefabAttribute : HeaderAttribute
{
    // This attribute can be used to mark fields that should be injected with prefabs by Zenject.
    // It can be used in conjunction with MonoInstaller or other Zenject installation methods.
    public InjectPrefabAttribute() : base("Prefab references")
    {
    }
}

public abstract class MonoInstallerBase : MonoInstaller
{
    public sealed override void InstallBindings()
    {
        RegisterGameObjects(Container);
        RegisterPrefabs(Container);
        RegisterServices(Container);
    }

    protected abstract void RegisterServices(DiContainer container);

    private void RegisterGameObjects(DiContainer container)
    {
        var gameObjects = GetRelevantGameObjects<InjectGameObjectAttribute>();
        InjectObjects(container, gameObjects);
    }

    private void RegisterPrefabs(DiContainer container)
    {
        var gameObjects = GetRelevantGameObjects<InjectPrefabAttribute>();
        InjectObjects(container, gameObjects);
    }

    
    private IEnumerable<GameObject> GetRelevantGameObjects<T>()
        where T : HeaderAttribute
    {
        var fields = GetType()
                .GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
                .Where(field => field.GetCustomAttributes(typeof(InjectGameObjectAttribute), false).Length > 0);

        foreach(var field in fields)
        {
            if (field.FieldType != typeof(GameObject) && !field.FieldType.IsSubclassOf(typeof(GameObject)))
            {
                Debug.LogError($"Field '{field.Name}' is not of type GameObject or a subclass. Skipping injection.");
                continue;
            }

            var instance = field.GetValue(this) as GameObject;
            if (instance == null)
            {
                Debug.LogError($"Field '{field.Name}' is null. Skipping injection.");
                continue;
            }

            yield return instance;
        }
    }

    private static void InjectObjects(DiContainer container, IEnumerable<GameObject> gameObjects)
    {
        foreach (var gameObject in gameObjects)
        {
            container.Inject(gameObject);
        }
    }


}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions