Ninject 2.0 - binding to an object that uses the same interface more than once?

Consider the following:

public Something(IInterface concreteObjectOne, IInterface concreteObjectTwo) { this.concreteObjectOne = concreteObjectOne; this.concreteObjectTwo = concreteObjectTwo; } 

How to set this type of binding using Ninject? I would try Googling this term, but since I'm not sure what it's called, I cannot, and I cannot find anything in the Wiki about this.

Edit

I believe this is called Convention-based binding, as described here . However, this documentation for versions 1.0 and 2.0 does not have an Only method. I would like this to be achieved without attributes - using a naming convention or something like that.

+6
c # ioc-container ninject binding
source share
2 answers

In addition to using the Only method, the article offers a different solution by setting different attributes for the entered objects.

Example:

 public class ObjectOneAttribute : Attribute { } public class ObjectTwoAttribute : Attribute { } 

Then

 public Something([ObjectOneAttribute] IInterface concreteObjectOne, [ObjectTwoAttribute] IInterface concreteObjectTwo) { this.concreteObjectOne = concreteObjectOne; this.concreteObjectTwo = concreteObjectTwo; } 

And when you want to bind the interface to a specific concrete object, use the "WhereTargetHas" method:

 Bind<IInterface>().To<YourConcreteTypeOne>().WhereTargetHas<ObjectOneAttribute>(); Bind<IInterface>().To<YourConcreteTypeTwo>().WhereTargetHas<ObjectTwoAttribute>(); 

Update: Solution without using attributes:
Use the When Method:

 Bind<IInterface>().To<YourConcreteTypeOne>().When(r => r.Target.Name == "concreteObjectOne"); Bind<IInterface>().To<YourConcreteTypeTwo>().When(r => r.Target.Name == "concreteObjectTwo") 

;

+9
source share

If I am allowed to offer some general, and not specific to Ninject, indications of this, I would suggest that you review your design a bit. The current constructor is vague because it gives no indication of which IInterface implementation goes there - I understand that this is just a mockup of your real API, and although the real API can offer additional help to the human developer in the form of exactly named parameters A machine like a DI container cannot infer proper use.

Many DI containers offer some way to solve this uncertainty, for example, by providing attributes that you can use to associate names (metadata) with each dependency. AFAIR, Ninject has Inject attributes ...

However, consider a few alternatives:

The first option is to encapsulate two similar instances of the interface in the Parameter Object , for example:

 public interface IParameterObject { IInterface ObjectOne { get; } IInterface ObjectTwo { get; } } 

Now you can change the constructor to take an instance of IParameterObject instead of the two instances of the interface themselves.

 public Something(IParameterObject po) { this.concreteObjectOne = po.ObjectOne; this.concreteObjectTwo = po.ObjectTwo; } 

This means that you can configure the IParameterObject configuration to the composition Root .

Another alternative to pondering is whether it makes sense to consider a two-instance case as a special case of a more general design that accepts any number of instances. This may not always be the case, but if it is, you can change the constructor to this:

 public Something(IEnumerable<IInterface> objects) 

I personally would prefer any of the above suggestions for using certain Ninject functions, because it makes me make the API more explicit in general and therefore more readable and maintainable.

+5
source share

All Articles