I have an MVC application using Ninject for DI and I'm planning to migrate the same to Simple Injector. But I couldn't find any alternatives for replacing the named binding of Ninject with Simple Injector.
Binding:
kernel.Bind<IStudent>().To<Student1>().Named("Senior");
kernel.Bind<IStudent>().To<Student2>().Named("Junior");
kernel.Bind<IStudent>().To<Student3>().Named("Junior");
Controller:
public class StudentController
{
private readonly IEnumerable<IStudent> _seniors;
private readonly IEnumerable<IStudent> _juniors;
public StudentController([named("Senior")] IEnumerable<IStudent> seniors,[named("Junior")] IEnumerable<IStudent> juniors)
{
_seniors=seniors;
_juniors=juniors;
}
}
I referred few links How to use Ninject's Named bindings in Simple Injector. But didn't have any luck.
There are many options:
Option 1: Using the [named] attribute
To achieve this, you will have to recreate the
NamedAttribute, since this is not something that exists in Simple Injector, for good reason.You can make the following two conditional registrations for collections of students:
Each conditional registration wraps a
Registrationfor anIStudentcollection. The predicate filters the target, in this case the constructor argument, for the name of itsnamedAttribute.Option 2: Without the named attribute, by checking the argument name
A simpler option, however, is to ditch the named attribute alltogether, and just filter based on the name of the constructor argument:
This registration is almost the same as with option 1, but now we filter based on the actual name of the argument, instead of based on its attribute.
Option 3: By manually wiring StudentsController.
An even simpler option is to revert from Auto-Wiring
StudentsControllerto wiring it manually, as follows:Here we request the Container to create the two collection of students, and create the registration for
StudentsControllerwhere both collections are injected into.Do note that in Simple Injector collections are streams. This means that the call to
Collection.Createdoes not create the student instances, just a reference to a stream that will produce student instances when iterated. This means, the stream can be created at application startup, while the registrations lifestyles are preserved.Also note that if you're calling
RegisterMvcControllers, you will have to override the existing registration for this controller class. This page shows how to do this.Option 4: Changing the design. Make 'Level' a property of IStudent. Filter inside the controller.
You can decide to change your design in a way that registration is simplified. Whether this is better highly depends on the context, so please take this with a grain of salt. However, when you add a
Levelproperty, or something similar, to theIStudentinterface that represents whether a student is a senior, and filter based on that inside the controller, your registrations are very much reduced to the following:Here we use Auto-Registration to search for all student implementations and register them all into one single collection.
In this case the
StudentControllerwill be left with a single constructor parameter, but you obviously moved the responsibility for filtering out of the Composition Root, into the controller.