using System; using System.Collections.Generic; using ModestTree; namespace Zenject { [NoReflectionBaking] public class CachedProvider : IProvider { readonly IProvider _creator; List _instances; #if ZEN_MULTITHREADING readonly object _locker = new object(); #else bool _isCreatingInstance; #endif public CachedProvider(IProvider creator) { _creator = creator; } public bool IsCached { get { return true; } } public bool TypeVariesBasedOnMemberType { get { // Should not call this throw Assert.CreateException(); } } public int NumInstances { get { #if ZEN_MULTITHREADING lock (_locker) #endif { return _instances == null ? 0 : _instances.Count; } } } // This method can be called if you want to clear the memory for an AsSingle instance, // See isssue https://github.com/svermeulen/Zenject/issues/441 public void ClearCache() { #if ZEN_MULTITHREADING lock (_locker) #endif { _instances = null; } } public Type GetInstanceType(InjectContext context) { return _creator.GetInstanceType(context); } public void GetAllInstancesWithInjectSplit( InjectContext context, List args, out Action injectAction, List buffer) { Assert.IsNotNull(context); #if ZEN_MULTITHREADING lock (_locker) #endif { if (_instances != null) { injectAction = null; buffer.AllocFreeAddRange(_instances); return; } #if !ZEN_MULTITHREADING // This should only happen with constructor injection // Field or property injection should allow circular dependencies if (_isCreatingInstance) { var instanceType = _creator.GetInstanceType(context); throw Assert.CreateException( "Found circular dependency when creating type '{0}'. Object graph:\n {1}{2}\n", instanceType, context.GetObjectGraphString(), instanceType); } _isCreatingInstance = true; #endif var instances = new List(); _creator.GetAllInstancesWithInjectSplit(context, args, out injectAction, instances); Assert.IsNotNull(instances); _instances = instances; #if !ZEN_MULTITHREADING _isCreatingInstance = false; #endif buffer.AllocFreeAddRange(instances); } } } }