Beispiel #1
0
        public void GlobalSetup()
        {
            var ninjectSettings = new NinjectSettings {
                LoadExtensions = false
            };

            var kernelConfiguration = new KernelConfiguration(ninjectSettings);

            kernelConfiguration.Bind <IWarrior>().To <SpecialNinja>().WhenInjectedExactlyInto <NinjaBarracks>();
            kernelConfiguration.Bind <IWarrior>().To <Samurai>().WhenInjectedExactlyInto <Barracks>();
            kernelConfiguration.Bind <IWarrior>().To <FootSoldier>().WhenInjectedExactlyInto <Barracks>();
            kernelConfiguration.Bind <IWeapon>().To <Shuriken>().WhenInjectedExactlyInto <Barracks>();
            kernelConfiguration.Bind <IWeapon>().To <ShortSword>().WhenInjectedExactlyInto <Spartan>();

            _injectorFactory = new ExpressionInjectorFactory();

            _contextWithParams = CreateContext(kernelConfiguration,
                                               kernelConfiguration.BuildReadOnlyKernel(),
                                               new List <IParameter>
            {
                new ConstructorArgument("height", 34),
                new PropertyValue("name", "cutter"),
                new ConstructorArgument("width", 17),
                new ConstructorArgument("location", "Biutiful")
            },
                                               typeof(StandardConstructorScorerBenchmark),
                                               ninjectSettings);

            _contextWithoutParams = CreateContext(kernelConfiguration,
                                                  kernelConfiguration.BuildReadOnlyKernel(),
                                                  Enumerable.Empty <IParameter>(),
                                                  typeof(StandardConstructorScorerBenchmark),
                                                  ninjectSettings);

            _injectCtor          = typeof(NinjaBarracks).GetConstructor(new[] { typeof(IWarrior), typeof(IWeapon) });
            _injectCtorDirective = new ConstructorInjectionDirective(_injectCtor, _injectorFactory.Create(_injectCtor));

            _defaultCtor          = typeof(NinjaBarracks).GetConstructor(new Type[0]);
            _defaultCtorDirective = new ConstructorInjectionDirective(_defaultCtor, _injectorFactory.Create(_defaultCtor));

            _knifeCtor          = typeof(Knife).GetConstructor(new[] { typeof(int), typeof(int) });
            _knifeCtorDirective = new ConstructorInjectionDirective(_knifeCtor, _injectorFactory.Create(_knifeCtor));

            _knifeDefaultsCtor          = typeof(Knife).GetConstructor(new[] { typeof(bool), typeof(string) });
            _knifeDefaultsCtorDirective = new ConstructorInjectionDirective(_knifeDefaultsCtor, _injectorFactory.Create(_knifeDefaultsCtor));

            _spartanNameAndAgeCtor          = typeof(Spartan).GetConstructor(new[] { typeof(string), typeof(int) });
            _spartanNameAndAgeCtorDirective = new ConstructorInjectionDirective(_spartanNameAndAgeCtor, _injectorFactory.Create(_spartanNameAndAgeCtor));

            _spartanHeightAndWeaponCtor          = typeof(Spartan).GetConstructor(new[] { typeof(string), typeof(int) });
            _spartanHeightAndWeaponCtorDirective = new ConstructorInjectionDirective(_spartanHeightAndWeaponCtor, _injectorFactory.Create(_spartanHeightAndWeaponCtor));

            _barracksCtor          = typeof(Barracks).GetConstructor(new[] { typeof(IWarrior), typeof(IWeapon) });
            _barracksCtorDirective = new ConstructorInjectionDirective(_barracksCtor, _injectorFactory.Create(_barracksCtor));

            _monasteryCtor          = typeof(Monastery).GetConstructor(new[] { typeof(IWarrior), typeof(IWeapon) });
            _monasteryCtorDirective = new ConstructorInjectionDirective(_monasteryCtor, _injectorFactory.Create(_monasteryCtor));

            _standardConstructorScorer = new StandardConstructorScorer(ninjectSettings);
        }
		/*----------------------------------------------------------------------------------------*/
		#region Public Methods
		/// <summary>
		/// Creates an injection directive for the specified constructor.
		/// </summary>
		/// <param name="binding">The binding.</param>
		/// <param name="constructor">The constructor to create the directive for.</param>
		/// <returns>The created directive.</returns>
		public ConstructorInjectionDirective Create(IBinding binding, ConstructorInfo constructor)
		{
			var directive = new ConstructorInjectionDirective(constructor);
			CreateArgumentsForMethod(binding, constructor).Each(directive.Arguments.Add);

			return directive;
		}
Beispiel #3
0
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public virtual int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, "context");
            Ensure.ArgumentNotNull(directive, "constructor");

            if (directive.HasInjectAttribute)
            {
                return(int.MaxValue);
            }

            var score = 1;

            foreach (ITarget target in directive.Targets)
            {
                if (ParameterExists(context, target))
                {
                    score++;
                    continue;
                }

                if (BindingExists(context, target))
                {
                    score++;
                    continue;
                }

                score++;
                if (score > 0)
                {
                    score += int.MinValue;
                }
            }

            return(score);
        }
        public void Create_ShouldUseConstructorArgumentsForBestConstructor()
        {
            var seq = new MockSequence();

            var injectorOneMock = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var injectorTwoMock = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var directiveOne    = new ConstructorInjectionDirective(GetMyServiceWeaponAndWarriorConstructor(), injectorOneMock.Object);
            var directiveTwo    = new ConstructorInjectionDirective(GetMyServiceClericAndName(), injectorTwoMock.Object);
            var name            = new Random().Next().ToString();
            var cleric          = new Monk();
            var instance        = new object();
            var parameters      = new List <IParameter>
            {
                new ConstructorArgument("name", name),
                new ConstructorArgument("weapon", new Dagger()),
                new ConstructorArgument("cleric", cleric),
            };

            var kernelConfiguration = new KernelConfiguration(_ninjectSettings);
            var context             = CreateContext(kernelConfiguration, kernelConfiguration.BuildReadOnlyKernel(), parameters, typeof(NinjaBarracks), _providerCallbackMock.Object, _ninjectSettings);

            context.Plan = new Plan(typeof(MyService));
            context.Plan.Add(directiveOne);
            context.Plan.Add(directiveTwo);

            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(context, directiveOne)).Returns(2);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(context, directiveTwo)).Returns(3);
            injectorTwoMock.InSequence(seq).Setup(p => p(cleric, name)).Returns(instance);

            var actual = _standardProvider.Create(context);

            Assert.Same(instance, actual);
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public virtual int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Contract.Requires(context != null);
            Contract.Requires(directive != null);

            if (directive.HasInjectAttribute)
            {
                return int.MaxValue;
            }

            var score = 1;
            foreach (ITarget target in directive.Targets)
            {
                if (this.ParameterExists(context, target))
                {
                    score++;
                    continue;
                }

                if (this.BindingExists(context, target))
                {
                    score++;
                    continue;
                }

                score++;
                if (score > 0)
                {
                    score += int.MinValue;
                }
            }

            return score;
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public virtual int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, "context");
            Ensure.ArgumentNotNull(directive, "constructor");

            if (directive.HasInjectAttribute)
            {
                return int.MaxValue;
            }

            var score = 1;
            foreach (ITarget target in directive.Targets)
            {
                if (ParameterExists(context, target))
                {
                    score++;
                    continue;
                }
                
                if (BindingExists(context, target))
                {
                    score++;
                    continue;
                }

                score++;
                if (score > 0)
                {
                    score += int.MinValue;
                }
            }
            
            return score;
        }
Beispiel #7
0
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public virtual int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Contract.Requires(context != null);
            Contract.Requires(directive != null);

            if (directive.HasInjectAttribute)
            {
                return(int.MaxValue);
            }

            var score = 1;

            foreach (ITarget target in directive.Targets)
            {
                if (this.ParameterExists(context, target))
                {
                    score++;
                    continue;
                }

                if (this.BindingExists(context, target))
                {
                    score++;
                    continue;
                }

                score++;
                if (score > 0)
                {
                    score += int.MinValue;
                }
            }

            return(score);
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, "context");
            Ensure.ArgumentNotNull(directive, "constructor");

            if(directive.Constructor.HasAttribute(Settings.InjectAttribute))
                return Int32.MaxValue;

            int score = 1;
            foreach(ITarget target in directive.Targets)
            {
                foreach(IParameter parameter in context.Parameters)
                {
                    if(string.Equals(target.Name, parameter.Name))
                    {
                        score++;
                        continue;
                    }
                }

                Type targetType = target.Type;
                if(targetType.IsArray)
                    targetType = targetType.GetElementType();

                if(targetType.IsGenericType && targetType.GetInterfaces().Any(type => type == typeof(IEnumerable)))
                    targetType = targetType.GetGenericArguments()[0];

                if(context.Kernel.GetBindings(targetType).Count() > 0)
                    score++;
            }

            return score;
        }
        /*----------------------------------------------------------------------------------------*/
        #region Public Methods
        /// <summary>
        /// Creates an injection directive for the specified constructor.
        /// </summary>
        /// <param name="binding">The binding.</param>
        /// <param name="constructor">The constructor to create the directive for.</param>
        /// <returns>The created directive.</returns>
        public ConstructorInjectionDirective Create(IBinding binding, ConstructorInfo constructor)
        {
            var directive = new ConstructorInjectionDirective(constructor);

            CreateArgumentsForMethod(binding, constructor).Each(directive.Arguments.Add);

            return(directive);
        }
Beispiel #10
0
        public void TwoArguments()
        {
            var directive = new ConstructorInjectionDirective(_twoArgumentConstructor, _twoArgumentIinjector);

            if (directive == null)
            {
                throw new Exception();
            }
        }
        /// <summary>
        /// Gets the score for the specified constructor. Looks at the number of "resolvable" arguments.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public int Score(IContext context, ConstructorInjectionDirective directive)
        {
            if (directive.Constructor.HasAttribute(Settings.InjectAttribute))
                return Int32.MaxValue;

            var bindableParameters = from param in directive.Constructor.GetParameters()
                                     where !param.IsOut && !param.IsRetval && !param.IsOptional
                                           && param.ParameterType.IsBindable(context.Kernel)
                                     select param;
            return bindableParameters.Count();
        }
Beispiel #12
0
        public PlanTests()
        {
            _constructor1 = CreateConstructorInjectionDirective();
            _constructor2 = CreateConstructorInjectionDirective();
            _property     = CreatePropertyInjectionDirective();

            _plan = new Plan(this.GetType());
            _plan.Add(_constructor1);
            _plan.Add(_property);
            _plan.Add(_constructor2);
        }
Beispiel #13
0
        /// <summary>
        /// Adds a serial of <see cref="ConstructorInjectionDirective"/>s to the plan for the constructors
        /// that could be injected.
        /// </summary>
        /// <param name="plan">The plan that is being generated.</param>
        /// <exception cref="ArgumentNullException"><paramref name="plan"/> is <see langword="null"/>.</exception>
        public void Execute(IPlan plan)
        {
            Ensure.ArgumentNotNull(plan, nameof(plan));

            var constructors = this.selector.SelectConstructorsForInjection(plan.Type);

            foreach (var constructor in constructors)
            {
                var directive = new ConstructorInjectionDirective(constructor, this.injectorFactory.Create(constructor));
                plan.Add(directive);
            }
        }
Beispiel #14
0
 public override int Score(IContext context, ConstructorInjectionDirective directive)
 {
     //has more than one constructor
     //and the constructor being considered is parameterless
     if (directive.Constructor.GetType().GetConstructors().Count() > 1 &&
         !directive.Targets.Any())
     {
         //give it a low score
         return(Int32.MinValue);
     }
     return(base.Score(context, directive));
 }
        /// <summary>
        /// Gets the score for the specified constructor. Looks at the number of "resolvable" arguments.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public int Score(IContext context, ConstructorInjectionDirective directive)
        {
            if (directive.Constructor.HasAttribute(Settings.InjectAttribute))
            {
                return(Int32.MaxValue);
            }

            var bindableParameters = from param in directive.Constructor.GetParameters()
                                     where !param.IsOut && !param.IsRetval && !param.IsOptional &&
                                     param.ParameterType.IsBindable(context.Kernel)
                                     select param;

            return(bindableParameters.Count());
        }
        /*----------------------------------------------------------------------------------------*/
        /// <summary>
        /// Executed to build the activation plan.
        /// </summary>
        /// <param name="binding">The binding that points at the type whose activation plan is being released.</param>
        /// <param name="type">The type whose activation plan is being manipulated.</param>
        /// <param name="plan">The activation plan that is being manipulated.</param>
        /// <returns>
        /// A value indicating whether to proceed or interrupt the strategy chain.
        /// </returns>
        public override StrategyResult Build(IBinding binding, Type type, IActivationPlan plan)
        {
            // Get the list of candidate constructors.
            ConstructorInfo[] candidates           = type.GetConstructors(Kernel.Options.GetBindingFlags());
            ConstructorInfo   injectionConstructor = binding.Components.MemberSelector.SelectConstructor(binding, plan, candidates);

            // If an injection constructor was found, create an injection directive for it.
            if (injectionConstructor != null)
            {
                ConstructorInjectionDirective directive = binding.Components.DirectiveFactory.Create(binding, injectionConstructor);
                plan.Directives.Add(directive);
            }

            return(StrategyResult.Proceed);
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, "context");
            Ensure.ArgumentNotNull(directive, "constructor");

            if (directive.Constructor.HasAttribute(Settings.InjectAttribute))
            {
                return(Int32.MaxValue);
            }

            int score = 1;

            foreach (ITarget target in directive.Targets)
            {
                if (ParameterExists(context, target))
                {
                    score++;
                    continue;
                }

                Type targetType = target.Type;
                if (targetType.IsArray)
                {
                    targetType = targetType.GetElementType();
                }

                if (targetType.IsGenericType && targetType.GetInterfaces().Any(type => type == typeof(IEnumerable)))
                {
                    targetType = targetType.GetGenericArguments()[0];
                }

                if (context.Kernel.GetBindings(targetType).Any())
                {
                    score++;
                }
                else
                {
                    score++;
                    if (score > 0)
                    {
                        score += Int32.MinValue;
                    }
                }
            }

            return(score);
        }
Beispiel #18
0
        public void Create_ShouldThrowInvalidOperationExceptionWhenNoConstructorArgumentIsAvailableForGivenParameterAndResolveReturnsMultipleResults()
        {
            var seq = new MockSequence();

            var injectorOneMock    = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var injectorTwoMock    = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var directiveOne       = new ConstructorInjectionDirective(GetMyServiceWeaponAndWarriorConstructor(), injectorOneMock.Object);
            var directiveTwo       = new ConstructorInjectionDirective(GetMyServiceClericAndName(), injectorTwoMock.Object);
            var readOnlyKernelMock = new Mock <IReadOnlyKernel>(MockBehavior.Strict);
            var childRequestMock   = new Mock <IRequest>(MockBehavior.Strict);
            var planMock           = new Mock <IPlan>(MockBehavior.Strict);
            var instance           = new object();
            var weaponMock         = new Mock <IWeapon>(MockBehavior.Strict);
            var warriorMock        = new Mock <IWarrior>(MockBehavior.Strict);
            var directives         = new[]

            {
                directiveOne,
                directiveTwo
            };

            var parameters = new List <IParameter>
            {
                new ConstructorArgument("name", "Foo"),
                new ConstructorArgument("weapon", weaponMock.Object),
                new ConstructorArgument("cleric", new Monk()),
            };

            _contextMock.InSequence(seq).Setup(p => p.Plan).Returns(_planMock.Object);
            _contextMock.InSequence(seq).Setup(p => p.Plan).Returns(_planMock.Object);
            _planMock.InSequence(seq).Setup(p => p.GetAll <ConstructorInjectionDirective>()).Returns(directives);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(_contextMock.Object, directiveOne)).Returns(3);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(_contextMock.Object, directiveTwo)).Returns(2);
            _contextMock.InSequence(seq).Setup(p => p.Parameters).Returns(parameters);
            _contextMock.InSequence(seq).Setup(p => p.Parameters).Returns(parameters);
            _contextMock.InSequence(seq).Setup(p => p.Request).Returns(_requestMock.Object);
            _requestMock.InSequence(seq).Setup(p => p.CreateChild(typeof(IWarrior), _contextMock.Object, It.IsAny <ParameterTarget>())).Returns(childRequestMock.Object);
            childRequestMock.InSequence(seq).SetupSet(p => p.IsUnique = true);
            _contextMock.InSequence(seq).Setup(p => p.Kernel).Returns(readOnlyKernelMock.Object);
            readOnlyKernelMock.InSequence(seq).Setup(p => p.Resolve(childRequestMock.Object)).Returns(new[] { warriorMock.Object, new FootSoldier() });

            var actualException = Assert.Throws <InvalidOperationException>(() => _standardProvider.Create(_contextMock.Object));

            Assert.Null(actualException.InnerException);
            Assert.Equal("Sequence contains more than one element", actualException.Message);
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor.</param>
        /// <returns>The constructor's score.</returns>
        public int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, "context");
            Ensure.ArgumentNotNull(directive, "constructor");

            if(directive.Constructor.HasAttribute(Settings.InjectAttribute))
                return Int32.MaxValue;
            int score = 1;
            foreach(ITarget target in directive.Targets)
            {
                if(context.Kernel.GetBindings(target.Type).Count() > 0)
                {
                    score++;
                }
            }
            return score;
        }
        /// <summary>
        /// Adds a <see cref="ConstructorInjectionDirective"/> to the plan for the constructor
        /// that should be injected.
        /// </summary>
        /// <param name="plan">The plan that is being generated.</param>
        public void Execute(IPlan plan)
        {
            IEnumerable<ConstructorInfo> constructors = Selector.SelectConstructorsForInjection(plan.Type);
            if(constructors == null)
                return;

            foreach(ConstructorInfo constructor in constructors)
            {
                var hasInjectAttribute = constructor.HasAttribute(Settings.InjectAttribute);
                var directive = new ConstructorInjectionDirective(constructor, InjectorFactory.Create(constructor))
                {
                     HasInjectAttribute = hasInjectAttribute
                };

                plan.Add(directive);
            }
        }
        public void Create_ShouldPassResolvedObjectForGivenParameterWhenNoConstructorArgumentIsAvailableForParameterAndResolveReturnsSingleResult()
        {
            var seq = new MockSequence();

            var injectorOneMock    = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var injectorTwoMock    = new Mock <ConstructorInjector>(MockBehavior.Strict);
            var directiveOne       = new ConstructorInjectionDirective(GetMyServiceWeaponAndWarriorConstructor(), injectorOneMock.Object);
            var directiveTwo       = new ConstructorInjectionDirective(GetMyServiceClericAndName(), injectorTwoMock.Object);
            var weaponMock         = new Mock <IWeapon>(MockBehavior.Strict);
            var warriorMock        = new Mock <IWarrior>(MockBehavior.Strict);
            var readOnlyKernelMock = new Mock <IReadOnlyKernel>(MockBehavior.Strict);
            var childRequestMock   = new Mock <IRequest>(MockBehavior.Strict);
            var planMock           = new Mock <IPlan>(MockBehavior.Strict);
            var expected           = new object();
            var directives         = new[]
            {
                directiveOne,
                directiveTwo
            };

            var parameters = new List <IParameter>
            {
                new ConstructorArgument("name", "Foo"),
                new ConstructorArgument("weapon", weaponMock.Object),
                new ConstructorArgument("cleric", new Monk()),
            };

            _contextMock.InSequence(seq).Setup(p => p.Plan).Returns(_planMock.Object);
            _contextMock.InSequence(seq).Setup(p => p.Plan).Returns(_planMock.Object);
            _planMock.InSequence(seq).Setup(p => p.GetAll <ConstructorInjectionDirective>()).Returns(directives);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(_contextMock.Object, directiveOne)).Returns(3);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(_contextMock.Object, directiveTwo)).Returns(2);
            _contextMock.InSequence(seq).Setup(p => p.Parameters).Returns(parameters);
            _contextMock.InSequence(seq).Setup(p => p.Parameters).Returns(parameters);
            _contextMock.InSequence(seq).Setup(p => p.Request).Returns(_requestMock.Object);
            _requestMock.InSequence(seq).Setup(p => p.CreateChild(typeof(IWarrior), _contextMock.Object, It.IsAny <ParameterTarget>())).Returns(childRequestMock.Object);
            childRequestMock.InSequence(seq).SetupSet(p => p.IsUnique = true);
            _contextMock.InSequence(seq).Setup(p => p.Kernel).Returns(readOnlyKernelMock.Object);
            readOnlyKernelMock.InSequence(seq).Setup(p => p.ResolveSingle(childRequestMock.Object)).Returns(warriorMock.Object);
            injectorOneMock.InSequence(seq).Setup(p => p(weaponMock.Object, warriorMock.Object)).Returns(expected);

            var actual = _standardProvider.Create(_contextMock.Object);

            Assert.Same(expected, actual);
        }
        /*----------------------------------------------------------------------------------------*/
        /// <summary>
        /// Resolves the arguments for the constructor defined by the specified constructor injection
        /// directive.
        /// </summary>
        /// <param name="context">The context in which the activation is occurring.</param>
        /// <param name="directive">The directive describing the injection constructor.</param>
        /// <returns>An array of arguments that can be passed to the constructor.</returns>
        protected virtual object[] ResolveConstructorArguments(IContext context, ConstructorInjectionDirective directive)
        {
            var contextFactory = context.Binding.Components.ContextFactory;
            var converter      = context.Binding.Components.Converter;

            var arguments = new object[directive.Arguments.Count];

            int index = 0;

            foreach (Argument argument in directive.Arguments)
            {
                // First, try to get the value from a context parameter.
                object value = context.Parameters.GetValueOf <ConstructorArgumentParameter>(argument.Target.Name, context);

                // Next, try to get the value from a binding parameter.
                if (value == null)
                {
                    value = context.Binding.Parameters.GetValueOf <ConstructorArgumentParameter>(argument.Target.Name, context);
                }

                // If no overrides have been declared, activate a service of the proper type to use as the value.
                if (value == null)
                {
                    // Create a new context in which the parameter's value will be activated.
                    IContext injectionContext = contextFactory.CreateChild(context, directive.Member,
                                                                           argument.Target, argument.Optional);

                    // Resolve the value to inject for the parameter.
                    value = argument.Resolver.Resolve(context, injectionContext);
                }

                // Convert the value if necessary.
                if (!converter.Convert(value, argument.Target.Type, out value))
                {
                    throw new ActivationException(ExceptionFormatter.CouldNotConvertValueForInjection(context, argument.Target, value));
                }

                arguments[index++] = value;
            }

            return(arguments);
        }
 /// <summary>
 /// Gets the score for the specified constructor.
 /// </summary>
 /// <param name="context">The injection context.</param>
 /// <param name="directive">The constructor.</param>
 /// <returns>The constructor's score.</returns>
 public override int Score(IContext context, ConstructorInjectionDirective directive)
 {
     if (context.Request.Service.IsGenericType &&
         context.Request.Service.GetGenericTypeDefinition() == typeof(Lazy <>))
     {
         if (directive.Constructor.GetParameters().Length == 1 &&
             directive.Constructor.GetParameters()[0].ParameterType.IsGenericType)
         {
             return(1);
         }
         else
         {
             return(0);
         }
     }
     else
     {
         return(base.Score(context, directive));
     }
 }
        /// <summary>
        /// Adds a <see cref="ConstructorInjectionDirective"/> to the plan for the constructor
        /// that should be injected.
        /// </summary>
        /// <param name="plan">The plan that is being generated.</param>
        public void Execute(IPlan plan)
        {
            var constructors = this.Selector.SelectConstructorsForInjection(plan.Type);

            if (constructors == null)
            {
                return;
            }

            foreach (ConstructorInfo constructor in constructors)
            {
                var hasInjectAttribute = constructor.HasAttribute(this.Settings.InjectAttribute);
                var directive          = new ConstructorInjectionDirective(constructor, this.InjectorFactory.Create(constructor))
                {
                    HasInjectAttribute = hasInjectAttribute
                };

                plan.Add(directive);
            }
        }
        /// <summary>
        /// Gets the score for the specified constructor.
        /// </summary>
        /// <param name="context">The injection context.</param>
        /// <param name="directive">The constructor injection directive.</param>
        /// <returns>
        /// The constructor's score.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="context"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="directive"/> is <see langword="null"/>.</exception>
        public virtual int Score(IContext context, ConstructorInjectionDirective directive)
        {
            Ensure.ArgumentNotNull(context, nameof(context));
            Ensure.ArgumentNotNull(directive, nameof(directive));

            if (directive.Constructor.HasAttribute(this.settings.InjectAttribute))
            {
                return(int.MaxValue);
            }

            if (directive.Constructor.HasAttribute(typeof(ObsoleteAttribute)))
            {
                return(int.MinValue);
            }

            var score = 1;

            foreach (ITarget target in directive.Targets)
            {
                if (this.ParameterExists(context, target))
                {
                    score++;
                    continue;
                }

                if (this.BindingExists(context, target))
                {
                    score++;
                    continue;
                }

                score++;
                if (score > 0)
                {
                    score += int.MinValue;
                }
            }

            return(score);
        }
        public void Create_ShouldThrowActivationExceptionWhenThereIsMoreThanOneConstructorInjectionDirectiveWithTheBestScore()
        {
            var seq = new MockSequence();
            var constructorInjectorMock = new Mock <ConstructorInjector>(MockBehavior.Strict);

            var directiveOne   = new ConstructorInjectionDirective(GetMyServiceWeaponAndWarriorConstructor(), constructorInjectorMock.Object);
            var directiveTwo   = new ConstructorInjectionDirective(GetMyServiceDefaultConstructor(), constructorInjectorMock.Object);
            var directiveThree = new ConstructorInjectionDirective(GetMyServiceClericAndName(), constructorInjectorMock.Object);
            var directives     = new ConstructorInjectionDirective[]
            {
                directiveOne,
                directiveTwo,
                directiveThree
            };
            var parameters = new List <IParameter>
            {
                new ConstructorArgument("location", "Biutiful"),
                new ConstructorArgument("warrior", new Monk()),
                new ConstructorArgument("weapon", new Dagger())
            };

            var kernelConfiguration = new KernelConfiguration(_ninjectSettings);
            var context             = CreateContext(kernelConfiguration, kernelConfiguration.BuildReadOnlyKernel(), parameters, typeof(NinjaBarracks), _providerCallbackMock.Object, _ninjectSettings);

            context.Plan = new Plan(typeof(MyService));
            context.Plan.Add(directiveOne);
            context.Plan.Add(directiveTwo);
            context.Plan.Add(directiveThree);

            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(context, directiveOne)).Returns(3);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(context, directiveTwo)).Returns(2);
            _constructorScorerMock.InSequence(seq).Setup(p => p.Score(context, directiveThree)).Returns(3);
            _providerCallbackMock.InSequence(seq).Setup(p => p(context)).Returns(_providerMock.Object);

            var actualException = Assert.Throws <ActivationException>(() => _standardProvider.Create(context));

            Assert.Null(actualException.InnerException);
            Assert.Equal(CreateAmbiguousConstructorExceptionMessage(actualException.GetType()), actualException.Message);
        }
Beispiel #27
0
        /// <summary>
        /// Creates an instance within the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>The created instance.</returns>
        public virtual object Create(IContext context)
        {
            Ensure.ArgumentNotNull(context, "context");

            if (context.Plan == null)
            {
                context.Plan = this.Planner.GetPlan(this.GetImplementationType(context.Request.Service));
            }

            ConstructorInjectionDirective directive = null;
            var directives = context.Plan.ConstructorInjectionDirectives;

            if (directives.Count == 1)
            {
                directive = directives[0];
            }
            else
            {
                var bestDirectives = directives
                                     .GroupBy(option => this.ConstructorScorer.Score(context, option))
                                     .OrderByDescending(g => g.Key)
                                     .FirstOrDefault();
                if (bestDirectives == null)
                {
                    throw new ActivationException(ExceptionFormatter.NoConstructorsAvailable(context));
                }

                if (bestDirectives.Skip(1).Any())
                {
                    throw new ActivationException(ExceptionFormatter.ConstructorsAmbiguous(context, bestDirectives));
                }

                directive = bestDirectives.First();
            }

            var arguments = directive.Targets.Select(target => this.GetValue(context, target)).ToArray();

            return(directive.Injector(arguments));
        }
        /// <summary>
        /// Adds a <see cref="ConstructorInjectionDirective"/> to the plan for the constructor
        /// that should be injected.
        /// </summary>
        /// <param name="plan">The plan that is being generated.</param>
        public void Execute(IPlan plan)
        {
            Ensure.ArgumentNotNull(plan, "plan");

            var constructors = this.selector.SelectConstructorsForInjection(plan.Type);

            if (constructors == null)
            {
                return;
            }

            foreach (ConstructorInfo constructor in constructors)
            {
                var hasInjectAttribute   = constructor.HasAttribute(this.settings.InjectAttribute);
                var hasObsoleteAttribute = constructor.HasAttribute(typeof(ObsoleteAttribute));
                var directive            = new ConstructorInjectionDirective(constructor, this.injectorFactory.Create(constructor))
                {
                    HasInjectAttribute   = hasInjectAttribute,
                    HasObsoleteAttribute = hasObsoleteAttribute,
                };

                plan.Add(directive);
            }
        }
        public void Create_ShouldThrowActivationExceptionWhenThereAreZeroConstructorInjectionDirectives()
        {
            var directives = new ConstructorInjectionDirective[0];
            var parameters = new List <IParameter>
            {
                new ConstructorArgument("location", "Biutiful"),
                new ConstructorArgument("warrior", new Monk()),
                new ConstructorArgument("weapon", new Dagger())
            };

            var kernelConfiguration = new KernelConfiguration(_ninjectSettings);
            var context             = CreateContext(kernelConfiguration, kernelConfiguration.BuildReadOnlyKernel(), parameters, typeof(NinjaBarracks), _providerCallbackMock.Object, _ninjectSettings);

            context.Plan = new Plan(typeof(NinjaBarracks));

            _providerCallbackMock.Setup(p => p(context)).Returns(_providerMock.Object);

            var actualException = Assert.Throws <ActivationException>(() => _standardProvider.Create(context));

            Assert.Null(actualException.InnerException);
            Assert.Equal(CreateNoConstructorAvailableExceptionMessage(), actualException.Message);

            _providerCallbackMock.Verify(p => p(context), Times.Once());
        }
 /// <summary>
 /// Gets the score for the specified constructor.
 /// </summary>
 /// <param name="context">The injection context.</param>
 /// <param name="directive">The constructor injection directive.</param>
 /// <returns>The constructor's score.</returns>
 public virtual int Score(IContext context, ConstructorInjectionDirective directive)
 {
     return(directive.Constructor.Equals(this.constructorInfo) ? 1 : 0);
 }
 /// <summary>
 /// Gets the score for the specified constructor.
 /// </summary>
 /// <param name="context">The injection context.</param>
 /// <param name="directive">The constructor.</param>
 /// <returns>The constructor's score.</returns>
 public virtual int Score(IContext context, ConstructorInjectionDirective directive)
 {
     return directive.Constructor.Equals(this.constructorInfo) ? 1 : 0;
 }
 public override int Score(IContext context, ConstructorInjectionDirective directive)
 {
     return directive.Targets.Length;
 }
		/*----------------------------------------------------------------------------------------*/
		/// <summary>
		/// Resolves the arguments for the constructor defined by the specified constructor injection
		/// directive.
		/// </summary>
		/// <param name="context">The context in which the activation is occurring.</param>
		/// <param name="directive">The directive describing the injection constructor.</param>
		/// <returns>An array of arguments that can be passed to the constructor.</returns>
		protected virtual object[] ResolveConstructorArguments(IContext context, ConstructorInjectionDirective directive)
		{
			var contextFactory = context.Binding.Components.ContextFactory;
			var converter = context.Binding.Components.Converter;

			var arguments = new object[directive.Arguments.Count];

			int index = 0;
			foreach (Argument argument in directive.Arguments)
			{
				// First, try to get the value from a context parameter.
				object value = context.Parameters.GetValueOf<ConstructorArgumentParameter>(argument.Target.Name, context);

				// Next, try to get the value from a binding parameter.
				if (value == null)
					value = context.Binding.Parameters.GetValueOf<ConstructorArgumentParameter>(argument.Target.Name, context);

				// If no overrides have been declared, activate a service of the proper type to use as the value.
        if (value == null)
				{
					// Create a new context in which the parameter's value will be activated.
					IContext injectionContext = contextFactory.CreateChild(context, directive.Member,
						argument.Target, argument.Optional);

					// Resolve the value to inject for the parameter.
					value = argument.Resolver.Resolve(context, injectionContext);
				}

				// Convert the value if necessary.
				if (!converter.Convert(value, argument.Target.Type, out value))
					throw new ActivationException(ExceptionFormatter.CouldNotConvertValueForInjection(context, argument.Target, value));

				arguments[index++] = value;
			}

			return arguments;
		}