Esempio n. 1
0
        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));
        }
Esempio n. 2
0
        /// <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;
        }