public object Get(Type type, CacheInfo info) { info = info.WithType(Nullable.GetUnderlyingType(type) ?? type); if (cache.TryGetValue(info, out var existing)) { return(existing); } return(parentContainer?.Get(type, info)); }
/// <summary> /// Caches an instance of a type as a type of <paramref name="type"/>. This instance will be returned each time you <see cref="Get(Type)"/>. /// </summary> /// <param name="type">The type to cache <paramref name="instance"/> as.</param> /// <param name="info">Extra information to identify <paramref name="instance"/> in the cache.</param> /// <param name="instance">The instance to cache. Must be or derive from <paramref name="type"/>.</param> /// <param name="allowValueTypes">Whether value types are allowed to be cached. /// This should only be used when it is guaranteed that the internal state of the type will remain consistent through retrieval. /// (e.g. <see cref="CancellationToken"/> or reference types).</param> internal void CacheAs(Type type, CacheInfo info, object instance, bool allowValueTypes) { if (instance == null) { if (allowValueTypes) { return; } throw new ArgumentNullException(nameof(instance)); } info = info.WithType(Nullable.GetUnderlyingType(type) ?? type); var instanceType = instance.GetType(); instanceType = Nullable.GetUnderlyingType(instanceType) ?? instanceType; if (instanceType.IsValueType && !allowValueTypes) { throw new ArgumentException($"{instanceType.ReadableName()} must be a class to be cached as a dependency.", nameof(instance)); } if (!info.Type.IsInstanceOfType(instance)) { throw new ArgumentException($"{instanceType.ReadableName()} must be a subclass of {info.Type.ReadableName()}.", nameof(instance)); } // We can theoretically make this work by adding a nested dependency container. That would be a pretty big change though. // For now, let's throw an exception as this leads to unexpected behaviours (depends on ordering of processing of attributes vs CreateChildDependencies). if (cache.TryGetValue(info, out _)) { throw new TypeAlreadyCachedException(info); } cache[info] = instance; }