Exemplo n.º 1
0
        private void SetConstructor(ConstructorCacheKey cacheKey, ConstructorCacheValue previousCacheValue, ConstructorInfo constructorInfo)
        {
            // Currently I choose last-win strategy but maybe other should be used
            _constructorCacheLock.PerformWrite(() =>
            {
                ConstructorCacheValue storedValue;
                if (!_constructorCache.TryGetValue(cacheKey, out storedValue))
                {
                    storedValue = ConstructorCacheValue.First();
                }

                if (storedValue.Version == previousCacheValue.Version)
                {
                    // Log.Debug("Everything is fine");
                }
                else if (storedValue.Version > previousCacheValue.Version)
                {
                    Log.Debug("Data in cache have been changed between read & write.");
                }
                else
                {
                    // TODO: Maybe exception should be thrown
                    Log.Debug("Something strange have happend. Deep log analyze required.");
                }
                // I'm not sure storedValue or previousCacheValue should be passed in here
                var cacheValue = ConstructorCacheValue.Next(storedValue, constructorInfo);
                _constructorCache[cacheKey] = cacheValue;
            });
        }
Exemplo n.º 2
0
            private bool Equals(ConstructorCacheKey other)
            {
                if (AutoCompleteDependecies != other.AutoCompleteDependecies)
                {
                    return(false);
                }

                return(string.Equals(Key, other.Key, StringComparison.Ordinal));
            }
Exemplo n.º 3
0
 private ConstructorCacheValue GetConstructor(ConstructorCacheKey cacheKey)
 {
     return(_constructorCacheLock.PerformRead(() =>
     {
         ConstructorCacheValue result;
         if (_constructorCache.TryGetValue(cacheKey, out result))
         {
             return result;
         }
         return ConstructorCacheValue.First();
     }));
 }
Exemplo n.º 4
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="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param>
        /// <param name="parameters">The parameters to inject.</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, bool autoCompleteDependencies, object[] parameters)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            lock (_lockObject)
            {
                var constructorCache    = GetConstructorCache(autoCompleteDependencies);
                var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, parameters);

                if (constructorCache.ContainsKey(constructorCacheKey))
                {
                    var cachedConstructor            = constructorCache[constructorCacheKey];
                    var instanceCreatedWithInjection = TryCreateWithConstructorInjectionWithParameters(typeToConstruct, cachedConstructor, parameters);
                    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);

                    constructorCache.Remove(constructorCacheKey);
                }

                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 typeConstructorsMetadata = GetTypeMetaData(typeToConstruct);
                var constructors             = typeConstructorsMetadata.GetConstructors(parameters.Count(), !autoCompleteDependencies);

                foreach (var constructor in constructors)
                {
                    // Check if this constructor is even possible
                    if (!CanConstructorBeUsed(constructor, autoCompleteDependencies, parameters))
                    {
                        continue;
                    }

                    Log.Debug("Using constructor '{0}' to construct type '{1}'", constructor.GetSignature(), typeToConstruct.FullName);

                    var instanceCreatedWithInjection = TryCreateWithConstructorInjectionWithParameters(typeToConstruct, constructor, parameters);
                    if (instanceCreatedWithInjection != null)
                    {
                        // We found a constructor that works, cache it
                        constructorCache[constructorCacheKey] = constructor;

                        return(instanceCreatedWithInjection);
                    }
                }

                Log.Debug("No constructor could be used, cannot construct type '{0}' with the specified parameters", typeToConstruct.FullName);

                return(null);
            }
        }
Exemplo n.º 5
0
 private bool Equals(ConstructorCacheKey other)
 {
     return(string.Equals(Key, other.Key, StringComparison.Ordinal));
 }
Exemplo n.º 6
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="parameters">The parameters to inject.</param>
        /// <param name="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param>
        /// <param name="preventCircularDependencies">if set to <c>true</c>, prevent circular dependencies using the <see cref="TypeRequestPath"/>.</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[] parameters,
                                                             bool autoCompleteDependencies, bool preventCircularDependencies = true)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            if (parameters == null)
            {
                parameters = new object[] { };
            }

            lock (_serviceLocator)
            {
                TypeRequestInfo typeRequestInfo = null;

                try
                {
                    if (preventCircularDependencies)
                    {
                        typeRequestInfo = new TypeRequestInfo(typeToConstruct);
                        if (_currentTypeRequestPath == null)
                        {
                            _currentTypeRequestPath = new TypeRequestPath(typeRequestInfo, name: TypeRequestPathName);
                        }
                        else
                        {
                            _currentTypeRequestPath.PushType(typeRequestInfo, true);
                        }
                    }

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

                    if (constructorCache.ContainsKey(constructorCacheKey))
                    {
                        var cachedConstructor            = constructorCache[constructorCacheKey];
                        var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, cachedConstructor,
                                                                                parameters, false, false);
                        if (instanceCreatedWithInjection != null)
                        {
                            if (preventCircularDependencies)
                            {
                                CompleteTypeRequestPathIfRequired(typeRequestInfo);
                            }

                            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);

                        constructorCache.Remove(constructorCacheKey);
                    }

                    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 typeConstructorsMetadata = GetTypeMetaData(typeToConstruct);
                    var constructors             = typeConstructorsMetadata.GetConstructors(parameters.Count(), !autoCompleteDependencies);

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

                        var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, constructor,
                                                                                parameters, true, i < constructors.Count - 1);
                        if (instanceCreatedWithInjection != null)
                        {
                            if (preventCircularDependencies)
                            {
                                CompleteTypeRequestPathIfRequired(typeRequestInfo);
                            }

                            // We found a constructor that works, cache it
                            constructorCache[constructorCacheKey] = 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)
                {
                    if (preventCircularDependencies)
                    {
                        CloseCurrentTypeIfRequired(typeRequestInfo);
                    }

                    Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName);

                    throw;
                }

                if (preventCircularDependencies)
                {
                    CloseCurrentTypeIfRequired(typeRequestInfo);
                }

                return(null);
            }
        }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
0
 private bool Equals(ConstructorCacheKey other)
 {
     return string.Equals(Key, other.Key, StringComparison.Ordinal);
 }
Exemplo n.º 9
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="parameters">The parameters to inject.</param>
        /// <param name="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param>
        /// <param name="preventCircularDependencies">if set to <c>true</c>, prevent circular dependencies using the <see cref="TypeRequestPath"/>.</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[] parameters,
            bool autoCompleteDependencies, bool preventCircularDependencies = true)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            if (parameters == null)
            {
                parameters = new object[] { };
            }

            lock (_serviceLocator)
            {
                TypeRequestInfo typeRequestInfo = null;

                try
                {
                    if (preventCircularDependencies)
                    {
                        typeRequestInfo = new TypeRequestInfo(typeToConstruct);
                        if (_currentTypeRequestPath == null)
                        {
                            _currentTypeRequestPath = new TypeRequestPath(typeRequestInfo, name: TypeRequestPathName);
                        }
                        else
                        {
                            _currentTypeRequestPath.PushType(typeRequestInfo, true);
                        }
                    }

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

                    if (constructorCache.ContainsKey(constructorCacheKey))
                    {
                        var cachedConstructor = constructorCache[constructorCacheKey];
                        var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, cachedConstructor,
                            parameters, false, false);
                        if (instanceCreatedWithInjection != null)
                        {
                            if (preventCircularDependencies)
                            {
                                CompleteTypeRequestPathIfRequired(typeRequestInfo);
                            }

                            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);

                        constructorCache.Remove(constructorCacheKey);
                    }

                    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 typeConstructorsMetadata = GetTypeMetaData(typeToConstruct);
                    var constructors = typeConstructorsMetadata.GetConstructors(parameters.Count(), !autoCompleteDependencies);

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

                        var instanceCreatedWithInjection = TryCreateToConstruct(typeToConstruct, constructor,
                            parameters, true, i < constructors.Count - 1);
                        if (instanceCreatedWithInjection != null)
                        {
                            if (preventCircularDependencies)
                            {
                                CompleteTypeRequestPathIfRequired(typeRequestInfo);
                            }

                            // We found a constructor that works, cache it
                            constructorCache[constructorCacheKey] = 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)
                {
                    if (preventCircularDependencies)
                    {
                        CloseCurrentTypeIfRequired(typeRequestInfo);
                    }

                    Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName);

                    throw;
                }

                if (preventCircularDependencies)
                {
                    CloseCurrentTypeIfRequired(typeRequestInfo);
                }

                return null;
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Creates an instance of the specified type using dependency injection.
        /// </summary>
        /// <param name="typeToConstruct">The type to construct.</param>
        /// <returns>The instantiated type using dependency injection.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="typeToConstruct"/> is <c>null</c>.</exception>
        public object CreateInstance(Type typeToConstruct)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            lock (_lockObject)
            {
                TypeRequestInfo typeRequestInfo = null;

                try
                {
                    typeRequestInfo = new TypeRequestInfo(typeToConstruct);
                    if (_currentTypeRequestPath == null)
                    {
                        _currentTypeRequestPath = new TypeRequestPath(typeRequestInfo, name: TypeRequestPathName);
                    }
                    else
                    {
                        _currentTypeRequestPath.PushType(typeRequestInfo, true);
                    }

                    var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, new object[] { });
                    if (_constructorCache.ContainsKey(constructorCacheKey))
                    {
                        var cachedConstructor            = _constructorCache[constructorCacheKey];
                        var instanceCreatedWithInjection = TryCreateWithConstructorInjection(typeToConstruct, cachedConstructor, false);
                        if (instanceCreatedWithInjection != null)
                        {
                            CompleteTypeRequestPathIfRequired(typeRequestInfo);

                            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);

                        _constructorCache.Remove(constructorCacheKey);
                    }

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

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

                        var instanceCreatedWithInjection = TryCreateWithConstructorInjection(typeToConstruct, constructor, i < constructors.Count - 1);
                        if (instanceCreatedWithInjection != null)
                        {
                            CompleteTypeRequestPathIfRequired(typeRequestInfo);

                            // We found a constructor that works, cache it
                            _constructorCache[constructorCacheKey] = constructor;

                            return(instanceCreatedWithInjection);
                        }
                    }

                    var createdInstanceUsingActivator = CreateInstanceUsingActivator(typeToConstruct);
                    if (createdInstanceUsingActivator != null)
                    {
                        CompleteTypeRequestPathIfRequired(typeRequestInfo);

                        return(createdInstanceUsingActivator);
                    }
                }
                catch (CircularDependencyException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    CloseCurrentTypeIfRequired(typeRequestInfo);

                    Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName);

                    throw;
                }

                CloseCurrentTypeIfRequired(typeRequestInfo);

                return(null);
            }
        }
Exemplo n.º 11
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="autoCompleteDependencies">if set to <c>true</c>, the additional dependencies will be auto completed.</param>
        /// <param name="parameters">The parameters to inject.</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, bool autoCompleteDependencies, object[] parameters)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            lock (_lockObject)
            {
                var constructorCache = GetConstructorCache(autoCompleteDependencies);
                var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, parameters);

                if (constructorCache.ContainsKey(constructorCacheKey))
                {
                    var cachedConstructor = constructorCache[constructorCacheKey];
                    var instanceCreatedWithInjection = TryCreateWithConstructorInjectionWithParameters(typeToConstruct, cachedConstructor, parameters);
                    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);

                    constructorCache.Remove(constructorCacheKey);
                }

                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 typeConstructorsMetadata = GetTypeMetaData(typeToConstruct);
                var constructors = typeConstructorsMetadata.GetConstructors(parameters.Count(), !autoCompleteDependencies);

                foreach (var constructor in constructors)
                {
                    // Check if this constructor is even possible
                    if (!CanConstructorBeUsed(constructor, autoCompleteDependencies, parameters))
                    {
                        continue;
                    }

                    Log.Debug("Using constructor '{0}' to construct type '{1}'", constructor.GetSignature(), typeToConstruct.FullName);

                    var instanceCreatedWithInjection = TryCreateWithConstructorInjectionWithParameters(typeToConstruct, constructor, parameters);
                    if (instanceCreatedWithInjection != null)
                    {
                        // We found a constructor that works, cache it
                        constructorCache[constructorCacheKey] = constructor;

                        return instanceCreatedWithInjection;
                    }
                }

                Log.Debug("No constructor could be used, cannot construct type '{0}' with the specified parameters", typeToConstruct.FullName);

                return null;
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Creates an instance of the specified type using dependency injection.
        /// </summary>
        /// <param name="typeToConstruct">The type to construct.</param>
        /// <returns>The instantiated type using dependency injection.</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="typeToConstruct"/> is <c>null</c>.</exception>
        public object CreateInstance(Type typeToConstruct)
        {
            Argument.IsNotNull("typeToConstruct", typeToConstruct);

            lock (_lockObject)
            {
                TypeRequestInfo typeRequestInfo = null;

                try
                {
                    typeRequestInfo = new TypeRequestInfo(typeToConstruct);
                    if (_currentTypeRequestPath == null)
                    {
                        _currentTypeRequestPath = new TypeRequestPath(typeRequestInfo, name: TypeRequestPathName);
                    }
                    else
                    {
                        _currentTypeRequestPath.PushType(typeRequestInfo, true);
                    }

                    var constructorCacheKey = new ConstructorCacheKey(typeToConstruct, new object[] { });
                    if (_constructorCache.ContainsKey(constructorCacheKey))
                    {
                        var cachedConstructor = _constructorCache[constructorCacheKey];
                        var instanceCreatedWithInjection = TryCreateWithConstructorInjection(typeToConstruct, cachedConstructor, false);
                        if (instanceCreatedWithInjection != null)
                        {
                            CompleteTypeRequestPathIfRequired(typeRequestInfo);

                            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);

                        _constructorCache.Remove(constructorCacheKey);
                    }

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

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

                        var instanceCreatedWithInjection = TryCreateWithConstructorInjection(typeToConstruct, constructor, i < constructors.Count - 1);
                        if (instanceCreatedWithInjection != null)
                        {
                            CompleteTypeRequestPathIfRequired(typeRequestInfo);

                            // We found a constructor that works, cache it
                            _constructorCache[constructorCacheKey] = constructor;

                            return instanceCreatedWithInjection;
                        }
                    }

                    var createdInstanceUsingActivator = CreateInstanceUsingActivator(typeToConstruct);
                    if (createdInstanceUsingActivator != null)
                    {
                        CompleteTypeRequestPathIfRequired(typeRequestInfo);

                        return createdInstanceUsingActivator;
                    }
                }
                catch (CircularDependencyException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    CloseCurrentTypeIfRequired(typeRequestInfo);

                    Log.Warning(ex, "Failed to construct type '{0}'", typeToConstruct.FullName);

                    throw;
                }

                CloseCurrentTypeIfRequired(typeRequestInfo);

                return null;
            }
        }