using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using VContainer.Internal; namespace VContainer.Unity { sealed class FindComponentProvider : IInstanceProvider { readonly Type componentType; readonly IReadOnlyList customParameters; ComponentDestination destination; Scene scene; public FindComponentProvider( Type componentType, IReadOnlyList customParameters, in Scene scene, in ComponentDestination destination) { this.componentType = componentType; this.customParameters = customParameters; this.scene = scene; this.destination = destination; } public object SpawnInstance(IObjectResolver resolver) { var component = default(Component); var parent = destination.GetParent(resolver); if (parent != null) { component = parent.GetComponentInChildren(componentType, true); if (component == null) { throw new VContainerException(componentType, $"{componentType} is not in the parent {parent.name} : {this}"); } } else if (scene.IsValid()) { using (ListPool.Get(out var gameObjectBuffer)) { scene.GetRootGameObjects(gameObjectBuffer); foreach (var gameObject in gameObjectBuffer) { component = gameObject.GetComponentInChildren(componentType, true); if (component != null) break; } } if (component == null) { throw new VContainerException(componentType, $"{componentType} is not in this scene {scene.path} : {this}"); } } else { throw new VContainerException(componentType, $"Invalid Component find target {this}"); } if (component is MonoBehaviour monoBehaviour) { var injector = InjectorCache.GetOrBuild(monoBehaviour.GetType()); injector.Inject(monoBehaviour, resolver, customParameters); } destination.ApplyDontDestroyOnLoadIfNeeded(component); return component; } } }