Почему Ninject настаивает на наличии привязки для Bool, когда я указал конструктор с параметром постоянного значения? - PullRequest
1 голос
/ 22 марта 2020

Я столкнулся с проблемой Ninject, которая, кажется, мне не совсем понятна. Может быть, вы видите что-то очевидное, что мне не хватает. Я получаю сообщение об ошибке привязки, когда требуется, чтобы у меня была привязка для Bool:

Ninject.ActivationException: Error activating bool
No matching bindings are available, and the type is not self-bindable.
Activation path:
  5) Injection of dependency bool into parameter realTime of constructor of type SimulatorStateMachine
  4) Injection of dependency ISimulatorStateTriggers into parameter stateMachine of constructor of type InputParser
  3) Injection of dependency InputParser into parameter parser of constructor of type SimulatorCommunicationsChannel
  2) Injection of dependency ICommunicationChannel into property Channel of type SimulatorContext
  1) Request for SimulatorContext

Suggestions:
  1) Ensure that you have defined a binding for bool.
  2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
  3) Ensure you have not accidentally created more than one kernel.
  4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
  5) If you are using automatic module loading, ensure the search path and filters are correct.

   at Ninject.KernelBase.Resolve(IRequest request, Boolean handleMissingBindings)
   at Ninject.KernelBase.Resolve(IRequest request)
   at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
   at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
   at Ninject.Activation.Providers.StandardProvider.c__DisplayClass15_0.b__0(ITarget target)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
   at Ninject.Activation.Context.ResolveInternal(Object scope)
   at Ninject.Activation.Context.Resolve()
   at Ninject.KernelBase.Resolve(IRequest request, Boolean handleMissingBindings)
   at Ninject.KernelBase.Resolve(IRequest request)
   at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
   at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
   at Ninject.Activation.Providers.StandardProvider.c__DisplayClass15_0.b__0(ITarget target)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
   at Ninject.Activation.Context.ResolveInternal(Object scope)
   at Ninject.Activation.Context.Resolve()
   at Ninject.KernelBase.Resolve(IRequest request, Boolean handleMissingBindings)
   at Ninject.KernelBase.Resolve(IRequest request)
   at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
   at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target)
   at Ninject.Activation.Providers.StandardProvider.c__DisplayClass15_0.b__0(ITarget target)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
   at Ninject.Activation.Context.ResolveInternal(Object scope)
   at Ninject.Activation.Context.Resolve()
   at Ninject.KernelBase.Resolve(IRequest request, Boolean handleMissingBindings)
   at Ninject.KernelBase.Resolve(IRequest request)
   at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent)
   at Ninject.Activation.Strategies.PropertyInjectionStrategy.GetValue(IContext context, ITarget target, IEnumerable`1 allPropertyValues)
   at Ninject.Activation.Strategies.PropertyInjectionStrategy.Activate(IContext context, InstanceReference reference)
   at Ninject.Activation.Pipeline.c__DisplayClass6_0.b__0(IActivationStrategy s)
   at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
   at Ninject.Activation.Pipeline.Activate(IContext context, InstanceReference reference)
   at Ninject.Activation.Context.ResolveInternal(Object scope)
   at Ninject.Activation.Context.Resolve()
   at Ninject.KernelBase.Resolve(IRequest request, Boolean handleMissingBindings)
   at Ninject.KernelBase.Resolve(IRequest request)
   at Ninject.ResolutionExtensions.GetResolutionIterator(IResolutionRoot root, Type service, Func`2 constraint, IEnumerable`1 parameters, Boolean isOptional, Boolean isUnique)
   at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
   at TA.SnapCap.Specifications.Contexts.SimulatorTestContextBuilder.Build() in C:\Users\Tim\source\repos\ta.snapcap\TA.SnapCap.Specifications\Contexts\SimulatorTestContextBuilder.cs:line 44
   at TA.SnapCap.Specifications.SimulatorSpecs.when_creating_a_fast_simulator.c.b__5_0() in C:\Users\Tim\source\repos\ta.snapcap\TA.SnapCap.Specifications\SimulatorSpecs\CreationSpecs.cs:line 32

Я не понимаю, зачем это нужно. Создаемый объект, SimulatorStateMachine, имеет специфическую c привязку к конструктору, который использует постоянное значение для аргумента bool. Я также попробовал вариант этого, используя .WithConstructorArgument().

Вся моя композиция root включена ниже. Если я раскомментирую строку Bind<bool>().ToConstant(false), ошибка исчезнет (но если, конечно, это не то поведение, которое мне нужно). Очевидно, что Ninject почему-то не использует указанный мной конструктор. Вы понимаете, почему это так? Я не могу, и я стал немного слепым ...

using System;
using Ninject;
using Ninject.Modules;
using NodaTime;
using TA.Ascom.ReactiveCommunications;
using TA.SnapCap.HardwareSimulator;

namespace TA.SnapCap.Specifications.Contexts
    {
    class SimulatorTestContextBuilder : NinjectModule
        {
        private readonly IKernel testKernel = new StandardKernel();
        string connectionString = "Simulator:Fast";
        Action<SimulatorStateMachine>
            initializeStateMachine = machine => { }; // called to initialize the state machine. DO nothing by default.
        bool openChannel;

        /// <inheritdoc />
        public override void Load()
            {
            //Bind<bool>().ToConstant(false);
            Bind<SimulatorStateMachine>().ToMethod(ctx => new SimulatorStateMachine(true, SystemClock.Instance));
            Bind<IClock>().ToMethod(_ => SystemClock.Instance).InSingletonScope();
            Bind<SimulatorEndpoint>()
                .ToMethod(ctx => SimulatorEndpoint.FromConnectionString(connectionString))
                .InSingletonScope();
            Bind<DeviceEndpoint>().To<SimulatorEndpoint>().InSingletonScope();
            Bind<InputParser>().ToSelf().InSingletonScope();
            Bind<ISimulatorStateTriggers>().To<SimulatorStateMachine>().InSingletonScope();
            Bind<SimulatorCommunicationsChannel>().ToSelf().InSingletonScope();
            Bind<ICommunicationChannel>().To<SimulatorCommunicationsChannel>().InSingletonScope();
            Bind<SimulatorContext>().ToSelf().InSingletonScope();
            }

        public SimulatorContext Build()
            {
            testKernel.Load(this);
            var context = testKernel.Get<SimulatorContext>();
            context.SimulatorChannel.IsOpen = openChannel;
            initializeStateMachine(context.Simulator);
            return context;
            }

        public SimulatorTestContextBuilder WithFastSimulator()
            {
            connectionString = "Simulator:Fast";
            return this;
            }

        public SimulatorTestContextBuilder WithRealtimeSimulator()
            {
            connectionString = "Simulator:Realtime";
            return this;
            }

        public SimulatorTestContextBuilder WithOpenChannel()
            {
            openChannel = true;
            return this;
            }

        public SimulatorTestContextBuilder InClosedState()
            {
            initializeStateMachine = machine =>
                machine.Initialize(new StateClosed(machine), testKernel.Get<InputParser>());
            return this;
            }
        }
    }

1 Ответ

1 голос
/ 24 марта 2020

Проблема с вашей привязкой ISimulatorStateTriggers. Это должно быть:

Bind<ISimulatorStateTriggers>()
  .ToMethod(ctx => new SimulatorStateMachine(yourChoiceOfBoolValue, SystemClock.Instance))
  .InSingletonScope();

Ваша привязка SimulatorStateMachine будет использоваться, только если вы решите SimulatorStateMachine, что здесь не так. Привязки не являются перегрузками для конструктора в этом случае.

...