Reputation: 13
I have the following code:
namespace Test.Ninject.ConstructorArgumentBug
{
public class ClassA
{
private readonly IDependecy _dependecy;
public ClassA(IDependecy dependecy)
{
_dependecy = dependecy;
}
}
public interface IDependecy
{
}
public class ConcreteDependency : IDependecy
{
private readonly string _arg;
public ConcreteDependency(string arg)
{
_arg = arg;
}
}
public class Tests
{
[Test]
public void Test1()
{
var kernel = new StandardKernel();
kernel.Bind<IDependecy>()
.To<ConcreteDependency>()
.WhenInjectedInto<ClassA>()
.WithConstructorArgument(new ConstructorArgument("arg", "test"));
var classA = kernel.Get<ClassA>();
Assert.IsNotNull(classA);
}
[Test]
public void Test2()
{
var kernel = new StandardKernel();
kernel.Bind<IDependecy>()
.To<ConcreteDependency>()
.WhenInjectedInto<ClassA>()
.WithConstructorArgument("arg", "test");
var classA = kernel.Get<ClassA>();
Assert.IsNotNull(classA);
}
}
}
The Test1 doesn't work, but the Test2 does, and I believe they should behave the same. It looks like a bug to me. For some reason the first test cannot resolve dependency with the following error:
Ninject.ActivationException : Error activating string No matching bindings are available, and the type is not self-bindable. Activation path: 3) Injection of dependency string into parameter arg of constructor of type ConcreteDependency 2) Injection of dependency IDependecy into parameter dependecy of constructor of type ClassA 1) Request for ClassA
I guess if the first test fails the second should fail too. Am I doing something wrong?
Thanks!
Upvotes: 1
Views: 638
Reputation: 27861
In Test1
, the WithConstructorArgument
method that you are invoking has the following signature:
IBindingWithOrOnSyntax<T> WithConstructorArgument<TValue>(TValue value);
Here is what the documentation says about this method (you get this on IntelliSense):
Indicates that the specified constructor argument should be overridden with the specified value.
And here is the documentation for TValue
:
Specifies the argument type to override
And here is the documentation for value
:
The value for the argument
So, this line:
.WithConstructorArgument(new ConstructorArgument("arg", "test"));
Which is equivalent to (C# automatically infers TValue
):
.WithConstructorArgument<ConstructorArgument>(new ConstructorArgument("arg", "test"));
is telling NInject that the constructor of ConcreteDependency
has a parameter of type ConstructorArgument
, where in fact it has a parameter of type string
.
So you should change it to
.WithConstructorArgument<string>("test");
Or simpler:
.WithConstructorArgument("test");
Please note that there is no overload of WithConstructorArgument
that has a parameter of type ConstructorArgument
.
However, there is another method called WithParameter
that takes in an IParameter
.
Since ConstructorArgument
implements IParameter
, you can use this method to specify the constructor argument via ConstructorArgument
like this:
kernel.Bind<IDependecy>()
.To<ConcreteDependency>()
.WhenInjectedInto<ClassA>()
.WithParameter(new ConstructorArgument("arg", "test"));
Upvotes: 2