Reputation: 538
Here's the example code:
using Ninject;
using Ninject.Activation;
using Ninject.Extensions.Factory;
using Ninject.Planning.Targets;
using System;
using System.Linq;
namespace DI
{
public interface INumberFactory
{
Test Create(int a);
}
public class Test
{
public Test(int a) { }
}
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new FuncModule());
kernel.Bind<Test>().ToSelf().WithConstructorArgument("a" , (context, target) =>
{
Console.WriteLine("I'm trying to retrieve the constructor argument");
return 0;
});
kernel.Bind<INumberFactory>().ToFactory();
// Nothing is printed, even if it logically should be
kernel.Get<INumberFactory>().Create(1);
}
}
}
I have a simple factory, in my case, the INumberFactory. This factory takes an int parameter "a" and creates an instance of the class Test. I want to create this instance using the constructor parameter passed to the Create method of the INumberFactory.
I used WithConstructorArgument for that. I wanted to do some custom configuration as well -- that's why I'm using the overload that lets me pass the callback of the type Func. I'm very surprised that the callback doesn't get called at all.
It seems that the point is the name of the parameter. Both the constructor parameter and the factory parameter are named "a". But this might be a problem in the case when two things are named and the same and mean different things. That's why I'm wondering:
(1) Is this a bug or an expected behavior?
(2) Is there a way to prevent this "auto-passing"? I want to have full control over passing the constructor arguments.
Upvotes: 2
Views: 192
Reputation: 11841
Looking at the documentation the ToFactory()
will cause Ninject to create a dynamic proxy that behaves like the following with your code:
public class NumberFactory : INumberFactory
{
readonly IResolutionRoot resolutionRoot;
public NumberFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
Test INumberFactory.Create(int a)
{
return this.resolutionRoot.Get<Test>(
new ConstructorArgument("a", a));
}
}
Therefore it is not using the binding that you have specified with the WithConstructorArgument
, and will directly use the value that you pass as the argument to Create
.
Upvotes: 1