private static bool CanResolveParameter(ICherryServiceLocatorAndRegistry current,
            ParameterInfo constructorParameterInfo, InjectionParameter[] parameters)
        {
            if (parameters == null || parameters.Length == 0)
            {
                // Shotcut when no parameters provided
                return current.CanGet(constructorParameterInfo.ParameterType);
            }

            InjectionParameter namedParameter = parameters.SingleOrDefault(p => p.Key == constructorParameterInfo.Name);
            if (namedParameter != null)
            {
                return true;
            }

            InjectionParameter unnamedParameter = parameters.SingleOrDefault(
                p => string.IsNullOrEmpty(p.Key) &&
                     !ReferenceEquals(p.Value, null)
                     && constructorParameterInfo.ParameterType.IsInstanceOfType(p.Value));
            if (unnamedParameter != null)
            {
                return true;
            }

            return current.CanGet(constructorParameterInfo.ParameterType);
        }
        public object Get(ICherryServiceLocatorAndRegistry original, ICherryServiceLocatorAndRegistry current,
            InjectionParameter[] parameters)
        {
            ConstructorInfo[] allPublicConstructors = _targetType.GetConstructors();

            ConstructorInfo bestConstructor =
                allPublicConstructors.OrderByDescending(
                    c => c.GetParameters().Count(p => CanResolveParameter(current, p, parameters)))
                    .FirstOrDefault();

            if (bestConstructor == null)
            {
                throw new InvalidOperationException(
                    string.Format(
                        "Creating an instance of type \"{0}\" failed. This type has no public constructors that can be satisfied.",
                        _targetType));
            }

            ParameterInfo[] constructorParameterInfos = bestConstructor.GetParameters();

            ValidateParameters(constructorParameterInfos, parameters);

            var constructorParameters = new object[constructorParameterInfos.Length];
            for (int i = 0; i < constructorParameterInfos.Length; i++)
            {
                constructorParameters[i] = ResolveParameter(original, current, constructorParameterInfos, i, parameters);
            }

            object instance = bestConstructor.Invoke(constructorParameters);
            return instance;
        }
 public object Get(ICherryServiceLocatorAndRegistry original, ICherryServiceLocatorAndRegistry current, InjectionParameter[] parameters)
 {
     if (parameters != null && parameters.Length > 0)
     {
         throw new ArgumentException(string.Format("Since \"{0}\" is a singleton instance, you cannot use parameters to resolve it.", _instance), "parameters");
     }
     return _instance;
 }
        public object Get(ICherryServiceLocatorAndRegistry original, ICherryServiceLocatorAndRegistry current, InjectionParameter[] parameters)
        {
            if (parameters != null && parameters.Length > 0)
            {
                throw new ArgumentException(string.Format("Since \"{0}\" is a singleton instance, you cannot use parameters to resolve it.", _instance), "parameters");
            }

            if (_instance != null)
            {
                return _instance;
            }
            lock (_syncRoot)
            {
                if (_instance != null)
                {
                    return _instance;
                }
                var instance = (new PerResolveResolver(_targetType)).Get(original, current, parameters);
                _instance = instance;
                return instance;
            }
        }
 private IParameter ResolveParameterName(Type serviceKey, IBinding binding, ref Type resolvedType, InjectionParameter injectionParameter)
 {
     resolvedType = resolvedType ?? TypeToGetResolved(serviceKey, binding);
     var constructorParameter = resolvedType.GetConstructors().SelectMany(c => c.GetParameters())
         .First(p => p.ParameterType.IsInstanceOfType(injectionParameter.Value));
     return new ConstructorArgument(constructorParameter.Name, injectionParameter.Value);
 }
 private IParameter[] ModifyParameters(Type serviceKey, IBinding binding, InjectionParameter[] parameters)
 {
     if (parameters == null || parameters.Length == 0)
     {
         return null;
     }
     Type resolvedType = null;
     return
         parameters.Select(
             p => string.IsNullOrEmpty(p.Key) ? ResolveParameterName(serviceKey, binding, ref resolvedType, p) : new ConstructorArgument(p.Key, p.Value))
             .ToArray();
 }
 private ResolverOverride ResolveParameterName(Type serviceKey, ContainerRegistration registration,
     ref Type resolvedType, InjectionParameter injectionParameter)
 {
     resolvedType = resolvedType ?? TypeToGetResolved(serviceKey, registration);
     ParameterInfo constructorParameter = resolvedType.GetConstructors().SelectMany(c => c.GetParameters())
         .First(p => p.ParameterType.IsInstanceOfType(injectionParameter.Value));
     return new ParameterOverride(constructorParameter.Name, injectionParameter.Value);
 }
 private ResolverOverride[] ModifyParameters(Type serviceKey, ContainerRegistration registration,
     InjectionParameter[] parameters)
 {
     if (parameters == null || parameters.Length == 0)
     {
         return null;
     }
     Type resolvedType = null;
     return
         parameters.Select(
             p =>
                 string.IsNullOrEmpty(p.Key)
                     ? ResolveParameterName(serviceKey, registration, ref resolvedType, p)
                     : new ParameterOverride(p.Key, p.Value))
             .ToArray();
 }
        private static object ResolveParameter(ICherryServiceLocatorAndRegistry original,
            ICherryServiceLocatorAndRegistry current, ParameterInfo[] constructorParameterInfos, int i,
            InjectionParameter[] parameters)
        {
            ParameterInfo constructorParameterInfo = constructorParameterInfos[i];

            if (parameters == null || parameters.Length == 0)
            {
                // Shotcut when no parameters provided
                return current.Get(original, constructorParameterInfo.ParameterType);
            }

            InjectionParameter namedParameter = parameters.SingleOrDefault(p => p.Key == constructorParameterInfo.Name);
            if (namedParameter != null)
            {
                return namedParameter.Value;
            }

            // No matching named parameter found, so lets try if we have a single parameter that mathes the constructor parameter type
            InjectionParameter unnamedParameter = parameters.SingleOrDefault(
                p => string.IsNullOrEmpty(p.Key) &&
                     !ReferenceEquals(p.Value, null)
                     && constructorParameterInfo.ParameterType.IsInstanceOfType(p.Value));

            if (unnamedParameter != null)
            {
                return unnamedParameter.Value;
            }

            return current.Get(original, constructorParameterInfo.ParameterType);
        }
        private void ValidateParameters(IEnumerable<ParameterInfo> constructorParameterInfos, InjectionParameter[] parameters)
        {
            if (parameters == null || parameters.Length == 0)
            {
                return;
            }

            var namedParametersWithoutMatchingConstructorParameter =
                parameters.Where(
                    p => !string.IsNullOrEmpty(p.Key) && constructorParameterInfos.All(cp => cp.Name != p.Key));
            if (namedParametersWithoutMatchingConstructorParameter.Any())
            {
                throw new ArgumentException("The provided parameters contain parameter names that cannot be matched to the constructor of type " + _targetType, "parameters");
            }

            var unnamedParametersByType = parameters
                .Where(p => string.IsNullOrEmpty(p.Key) &&
                            !ReferenceEquals(p.Value, null))
                .GroupBy(p => p.Value.GetType())
                .Select(p => new {Type = p.Key, Count = p.Count()})
                .ToArray();

            if (unnamedParametersByType.Any(p => p.Count > 1))
            {
                throw new ArgumentException("The provided parameters contain multiple unnamed parameters with the same type", "parameters");
            }

            if (
                unnamedParametersByType.Any(
                    p => constructorParameterInfos.Count(cp => cp.ParameterType.IsAssignableFrom(p.Type)) > 1))
            {
                throw new ArgumentException("The provided parameters contain unnamed parameters that cannot be mapped unambiguously to the constructor of type " + _targetType, "parameters");
            }
        }