Example #1
0
        /// <summary>
        /// Resolves the type from a known container.
        /// </summary>
        /// <param name="serviceInfo">The service information.</param>
        /// <returns>
        /// An instance of the type registered on the service.
        /// </returns>
        /// <exception cref="ArgumentNullException">The <paramref name="serviceInfo" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The type is not found in any container.</exception>
        private object ResolveTypeFromKnownContainer(ServiceInfo serviceInfo)
        {
            Argument.IsNotNull("serviceInfo", serviceInfo);

            lock (_lockObject)
            {
                var previousTypeRequestPath = _currentTypeRequestPath.Value;
                try
                {
                    var typeRequestInfo = new TypeRequestInfo(serviceInfo.Type, serviceInfo.Tag);
                    _currentTypeRequestPath.Value = TypeRequestPath.Branch(previousTypeRequestPath, typeRequestInfo);

                    var registeredTypeInfo = _registeredTypes[serviceInfo];

                    var serviceType = serviceInfo.Type;
                    var tag         = serviceInfo.Tag;

                    var instance = registeredTypeInfo.CreateServiceFunc(registeredTypeInfo);

                    if (instance != null && instance is Type)
                    {
                        instance = _typeFactory.CreateInstance((Type)instance);
                    }

                    if (instance == null)
                    {
                        ThrowTypeNotRegisteredException(serviceType);
                    }

                    if (IsTypeRegisteredAsSingleton(serviceType, tag))
                    {
                        RegisterInstance(serviceType, instance, tag, this);
                    }

                    return(instance);
                }
                finally
                {
                    _currentTypeRequestPath.Value = previousTypeRequestPath;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Creates an instance of the specified type using the specified parameters as injection values.
        /// </summary>
        /// <param name="typeToConstruct">The type to construct.</param>
        /// <param name="tag">The preferred tag when resolving dependencies.</param>
        /// <param name="parameters">The parameters to inject.</param>
        /// <param name="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param>
        /// <returns>The instantiated type using dependency injection.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="typeToConstruct" /> is <c>null</c>.</exception>
        private object CreateInstanceWithSpecifiedParameters(Type typeToConstruct, object tag, object[] parameters, bool autoCompleteDependencies)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            if (parameters == null)
            {
                parameters = ArrayShim.Empty <object>();
            }

            var previousRequestPath = _currentTypeRequestPath.Value;

            try
            {
                var typeRequestInfo = new TypeRequestInfo(typeToConstruct);
                _currentTypeRequestPath.Value = TypeRequestPath.Branch(previousRequestPath, typeRequestInfo);

                var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, autoCompleteDependencies, parameters);

                var typeConstructorsMetadata = GetTypeMetaData(typeToConstruct);

                var constructorCacheValue = GetConstructor(constructorCacheKey);

                if (constructorCacheValue.ConstructorInfo != null)
                {
                    var cachedConstructor            = constructorCacheValue.ConstructorInfo;
                    var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, cachedConstructor, tag, parameters, false, false, typeConstructorsMetadata);
                    if (instanceCreatedWithInjection != null)
                    {
                        return(instanceCreatedWithInjection);
                    }

                    Log.Warning("Found constructor for type '{0}' in constructor, but it failed to create an instance. Removing the constructor from the cache", typeToConstruct.FullName);

                    SetConstructor(constructorCacheKey, constructorCacheValue, null);
                }

                Log.Debug("Creating instance of type '{0}' using specific parameters. No constructor found in the cache, so searching for the right one", typeToConstruct.FullName);

                var constructors = typeConstructorsMetadata.GetConstructors(parameters.Length, !autoCompleteDependencies).SortByParametersMatchDistance(parameters).ToList();

                for (int i = 0; i < constructors.Count; i++)
                {
                    var constructor = constructors[i];

                    var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, constructor, tag, parameters, true, i < constructors.Count - 1, typeConstructorsMetadata);
                    if (instanceCreatedWithInjection != null)
                    {
                        // We found a constructor that works, cache it
                        SetConstructor(constructorCacheKey, constructorCacheValue, constructor);

                        // Only update the rule when using a constructor for the first time, not when using it from the cache
                        ApiCop.UpdateRule <TooManyDependenciesApiCopRule>("TypeFactory.LimitDependencyInjection", x => x.SetNumberOfDependenciesInjected(typeToConstruct, constructor.GetParameters().Count()));

                        return(instanceCreatedWithInjection);
                    }
                }

                Log.Debug("No constructor could be used, cannot construct type '{0}' with the specified parameters", typeToConstruct.FullName);
            }
            catch (CircularDependencyException)
            {
                throw;
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName);

                throw;
            }
            finally
            {
                _currentTypeRequestPath.Value = previousRequestPath;
            }

            return(null);
        }