#if !NOT_UNITY3D using System; using System.Collections.Generic; using System.Linq; using ModestTree; using UnityEngine; using Zenject.Internal; namespace Zenject { [NoReflectionBaking] public abstract class AddToGameObjectComponentProviderBase : IProvider { readonly Type _componentType; readonly DiContainer _container; readonly List _extraArguments; readonly object _concreteIdentifier; readonly Action _instantiateCallback; public AddToGameObjectComponentProviderBase( DiContainer container, Type componentType, IEnumerable extraArguments, object concreteIdentifier, Action instantiateCallback) { Assert.That(componentType.DerivesFrom()); _extraArguments = extraArguments.ToList(); _componentType = componentType; _container = container; _concreteIdentifier = concreteIdentifier; _instantiateCallback = instantiateCallback; } public bool IsCached { get { return false; } } public bool TypeVariesBasedOnMemberType { get { return false; } } protected DiContainer Container { get { return _container; } } protected Type ComponentType { get { return _componentType; } } protected abstract bool ShouldToggleActive { get; } public Type GetInstanceType(InjectContext context) { return _componentType; } public void GetAllInstancesWithInjectSplit( InjectContext context, List args, out Action injectAction, List buffer) { Assert.IsNotNull(context); object instance; // We still want to make sure we can get the game object during validation var gameObj = GetGameObject(context); var wasActive = gameObj.activeSelf; if (wasActive && ShouldToggleActive) { // We need to do this in some cases to ensure that [Inject] always gets // called before awake / start gameObj.SetActive(false); } if (!_container.IsValidating || TypeAnalyzer.ShouldAllowDuringValidation(_componentType)) { if (_componentType == typeof(Transform)) // Treat transform as a special case because it's the one component that's always automatically added // Otherwise, calling AddComponent below will fail and return null // This is nice to allow doing things like // Container.Bind().FromNewComponentOnNewGameObject(); { instance = gameObj.transform; } else { instance = gameObj.AddComponent(_componentType); } Assert.IsNotNull(instance); } else { instance = new ValidationMarker(_componentType); } injectAction = () => { try { var extraArgs = ZenPools.SpawnList(); extraArgs.AllocFreeAddRange(_extraArguments); extraArgs.AllocFreeAddRange(args); _container.InjectExplicit(instance, _componentType, extraArgs, context, _concreteIdentifier); Assert.That(extraArgs.Count == 0); ZenPools.DespawnList(extraArgs); if (_instantiateCallback != null) { _instantiateCallback(context, instance); } } finally { if (wasActive && ShouldToggleActive) { gameObj.SetActive(true); } } }; buffer.Add(instance); } protected abstract GameObject GetGameObject(InjectContext context); } } #endif