Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple Injector Register All Services From Namespace

My Service Interfaces has a namespace of Services.Interfaces

The implementation of the Service Interfaces has a namespace of Web.UI.Services

I have 2 service implementations for example

  • IUserService which needs to register to UserService
  • ICountryService which needs to register to CountryService

This is how I currently register these services with SimpleInjector.

container.Register<IUserService, UserService> ();
container.Register<ICountryService, CountryService> ();

Problem: If I have over 100 services to exaggerate a bit. I need to go and add a line for each service.

How can I register all the implementations from one assembly to all the interfaces form another assembly using Simple Injector?

like image 560
Shane van Wyk Avatar asked Feb 26 '15 21:02

Shane van Wyk


2 Answers

You can do this by querying over the assembly with LINQ and reflection and register all the types:

var registrations =
    from type in typeof(UserService).Assembly.GetExportedTypes()
    where type.Namespace.StartsWith("Services.Interfaces")
    where type.GetInterfaces().Any()
    select new { Service = type.GetInterfaces().Single(), Implementation = type };

foreach (var reg in registrations) {
    container.Register(reg.Service, reg.Implementation);
}

This is described here.

If I have over 100 services to exaggerate a bit. I need to go and add a line for each service.

If this is the case, I would argue that there is something wrong with your design. The fact that you call your services IUserService and ICountryService is an indication that you are violating the Single Responsibility, Open/closed and Interface Segregation Principles. This can cause serious maintainability issues.

For an alternative design, take a look at the these two articles. The described design allows a much higher level of maintainability, makes it much easier to register your services, and makes applying cross-cutting concerns childs play (especially with Simple Injector).

like image 109
Steven Avatar answered Nov 14 '22 15:11

Steven


You're looking for "Convention over configuration". Simple injector calls this Batch / Automatic registration.

While major DI containers provides API for this, it seems Simple Injector leaves it with us; With bit of reflection and LINQ it is possible to register types as a batch, so Simple Injector provides no special API for this.

Idea is you scan the assembly for concrete types with some convention, looking at whether it implements any interface; if it does, then register it.

Here's the sample pulled from above link:

var repositoryAssembly = typeof(SqlUserRepository).Assembly;

var registrations =
    from type in repositoryAssembly.GetExportedTypes()
    where type.Namespace == "MyComp.MyProd.BL.SqlRepositories"
    where type.GetInterfaces().Any()
    select new { Service = type.GetInterfaces().Single(), Implementation = type };

foreach (var reg in registrations) {
    container.Register(reg.Service, reg.Implementation, Lifestyle.Transient);
} 

You can modify this code to apply your convention and register types in batch.

like image 36
Sriram Sakthivel Avatar answered Nov 14 '22 15:11

Sriram Sakthivel