Reputation: 51
In Ninject if there are multiple bindings are available for the same type then it shows error. Is there any way by which instead of showing error It binds it to null?
class TestModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
Bind<ITemp<SomeType>>().To<TempClass1>().Named("temp");
Bind<ITemp<SomeType>>().To<TempClass2>().Named("temp1");
Bind<Func<string, ITemp<SomeType>>>().ToMethod(ctx => name =>
{
Ninject.IKernel kernel = new StandardKernel(new NinjectSettings
{ AllowNullInjection = true },
new TestModule());
return kernel.Get<ITemp<SomeType>>(name);
});
}
}
//Test Class
public class TestClass
{
private readonly ITemp<SomeType> temp;
private readonly Func<string,ITemp<SomeType>> _createRepository;
public TestClass(ITemp<SomeType> temp = null,
Func<string,ITemp<SomeType>> _createRepository = null)
{
this.temp = temp;
this._createRepository = _createRepository;
}
public void fun(string bindingName = null){
if(bindingName != null){
var repo = _createRepository(bindingName);
repo.SomeFunction();
}
else {
temp.SomeFunction();
}
}
}
public static void Main()
{
Ninject.IKernel kernel = new StandardKernel(new NinjectSettings {
AllowNullInjection = true }, new TestModule());
var testObject = kernel.Get<TestClass>();
//if named bindings are used
//testObj.fun("temp");
//if named bindings are not defined then
//testObj.fun();
}
When I try to get an instance of TestClass it will say that cannot resolve ITemp multiple bindings are found. According to my requirement, I want temp field in the TestClass to be injected as null.
Upvotes: 1
Views: 739
Reputation: 56909
Null does not play well when using dependency injection. What you should do when you desire a service that represents a null
is to use the Null Object Pattern.
public class NullTemp : ITemp<SomeType>
{
// provide no-op implementation
public void DoSomething()
{
}
}
And then any null
check in the service implementation should be changed to check for a NullTemp
type instead.
//if (temp == null)
if (temp.GetType().Equals(typeof(NullTemp)))
Since you don't have any null
checking in your example for your nullable dependencies, it is hard to imagine how it is expected to work.
Upvotes: 1
Reputation: 1847
You can use named bindings for your dependencies.
From ninject wiki:
Named bindings are the simplest (and most common) form of conditional binding, and are used as follows:
In your type bindings, you register multiple type bindings for the same service type, but add binding metadata so you’ll be able to indicate which one is appropriate in your condition later:-
Bind<IWeapon>().To<Shuriken>().Named("Strong"); Bind<IWeapon>().To<Dagger>().Named("Weak");
At the target location, you indicate the name you want to use in the given context:-
class WeakAttack { readonly IWeapon _weapon; public WeakAttack([Named("Weak")] IWeapon weakWeapon){ _weapon = weakWeapon; } public void Attack(string victim){ Console.WriteLine(_weapon.Hit(victim)); } }
Alternately, you can programmatically request a specifically named instance of a service directly (but be careful – doing so directly is typically an instance of the Service Location antipattern) by doing:
kernel.Get<IWeapon>("Weak");
or you can use the attribute-based helpers to specify different cases
Upvotes: 1