/// <summary>
        /// Selects the best constructor from the available constructors.
        /// </summary>
        /// <param name="constructorBindings">Available constructors.</param>
        /// <returns>The best constructor.</returns>
        /// <exception cref='DependencyResolutionException'>A single unambiguous match could not be chosen.</exception>
        public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
        {
            if (constructorBindings == null) throw new ArgumentNullException("constructorBindings");
            if (constructorBindings.Length == 0) throw new ArgumentOutOfRangeException("constructorBindings");

            if (constructorBindings.Length == 1)
                return constructorBindings[0];

            var withLength = constructorBindings
                .Select(binding => new { Binding = binding, ConstructorParameterLength = binding.TargetConstructor.GetParameters().Length });

            var maxLength = withLength.Max(binding => binding.ConstructorParameterLength);

            var maximal = withLength
                .Where(binding => binding.ConstructorParameterLength == maxLength)
                .Select(ctor => ctor.Binding)
                .ToArray();

            if (maximal.Length == 1)
                return maximal[0];

            throw new DependencyResolutionException(string.Format(
                CultureInfo.CurrentCulture,
                MostParametersConstructorSelectorResources.UnableToChooseFromMultipleConstructors,
                maxLength,
                maximal[0].TargetConstructor.DeclaringType));
        }
        /// <summary>
        /// Selects the best constructor from the available constructors.
        /// </summary>
        /// <param name="constructorBindings">Available constructors.</param>
        /// <returns>The best constructor.</returns>
        /// <exception cref='DependencyResolutionException'>A single unambiguous match could not be chosen.</exception>
        public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
        {
            if (constructorBindings == null) throw new ArgumentNullException("constructorBindings");
            if (constructorBindings.Length == 0) throw new ArgumentOutOfRangeException("constructorBindings");

            if (constructorBindings.Length == 1)
                return constructorBindings[0];

            var withLength = constructorBindings
                .Select(binding => new { Binding = binding, ConstructorParameterLength = binding.TargetConstructor.GetParameters().Length });

            var maxLength = withLength.Max(binding => binding.ConstructorParameterLength);

            var maximal = withLength
                .Where(binding => binding.ConstructorParameterLength == maxLength)
                .Select(ctor => ctor.Binding)
                .ToArray();

            if (maximal.Length == 1)
                return maximal[0];

            throw new DependencyResolutionException(string.Format(
                "Cannot choose between multiple constructors with equal length {0} on type '{1}'. Select the constructor explicitly, with the UsingConstructor() configuration method, when the component is registered.",
                maxLength,
                maximal[0].TargetConstructor.DeclaringType));
        }
        public void WhenAnExceptionIsThrownFromAConstructor_TheInnerExceptionIsWrapped()
        {
            var ci = typeof(ThrowsInCtor).GetTypeInfo().DeclaredConstructors.Single();
            var cpb = new ConstructorParameterBinding(
                ci, Enumerable.Empty<Parameter>(), new ContainerBuilder().Build());
            var dx = Assert.Throws<DependencyResolutionException>(() =>
                cpb.Instantiate());

            Assert.True(dx.Message.Contains(typeof(ThrowsInCtor).Name));
            Assert.Equal(ThrowsInCtor.Message, dx.InnerException.Message);
        }
        /// <summary>
        /// Selects the best constructor from the available constructors.
        /// </summary>
        /// <param name="constructorBindings">Available constructors.</param>
        /// <returns>The best constructor.</returns>
        public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
        {
            if (constructorBindings == null) throw new ArgumentNullException("constructorBindings");

            var result = constructorBindings
                .Where(b => b.TargetConstructor.GetParameters().Select(p => p.ParameterType).SequenceEqual(_signature))
                .ToArray();

            if (result.Length == 1)
                return result[0];

            if (!constructorBindings.Any())
                throw new ArgumentException(MatchingSignatureConstructorSelectorResources.AtLeastOneBindingRequired);

            var targetTypeName = constructorBindings.First().TargetConstructor.DeclaringType.Name;
            var signature = string.Join(", ", _signature.Select(t => t.Name).ToArray());

            if (result.Length == 0)
                throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, MatchingSignatureConstructorSelectorResources.RequiredConstructorNotAvailable, targetTypeName, signature));

            throw new DependencyResolutionException(string.Format(CultureInfo.CurrentCulture, MatchingSignatureConstructorSelectorResources.TooManyConstructorsMatch, signature));
        }
Beispiel #5
0
        private ConstructorParameterBinding[] GetValidConstructorBindings(IComponentContext context, IEnumerable <Parameter> parameters)
        {
            // Most often, there will be no `parameters` and/or no `_defaultParameters`; in both of those cases we can avoid allocating.
            var prioritisedParameters = parameters.Any() ?
                                        (_defaultParameters.Length == 0 ? parameters : parameters.Concat(_defaultParameters)) :
                                        _defaultParameters;

            var constructorBindings = new ConstructorParameterBinding[_availableConstructors.Length];

            for (var i = 0; i < _availableConstructors.Length; ++i)
            {
                constructorBindings[i] = new ConstructorParameterBinding(_availableConstructors[i], prioritisedParameters, context);
            }

            // Copy-on-write; 99% of components will have a single constructor that can be instantiated.
            var validBindings = constructorBindings;

            for (var i = 0; i < constructorBindings.Length; ++i)
            {
                if (!constructorBindings[i].CanInstantiate)
                {
                    // Further optimisation opportunity here
                    validBindings = constructorBindings
                                    .Where(cb => cb.CanInstantiate)
                                    .ToArray();

                    break;
                }
            }

            if (validBindings.Length == 0)
            {
                throw new DependencyResolutionException(GetBindingFailureMessage(constructorBindings));
            }

            return(validBindings);
        }
Beispiel #6
0
 public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
 {
     return null;
 }
 /// <summary>
 /// Selects the best constructor from the available constructors.
 /// </summary>
 /// <param name="constructorBindings">Available constructors.</param>
 /// <returns>
 /// The best constructor.
 /// </returns>
 public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
 {
     return constructorBindings.First();
 }