Dependency injection is very useful for decoupling classes from specific implementations. Typically, I use constructor injection with Ninject as my IoC (inversion of control) container. However, I’ve always had to specify interface -> type bindings one by one. It’s very clunky.
A friend of mine asked me a question about Ninject mass bindings. This made me think that I should really streamline my own injection to deal with current and future repetitive bindings automatically. There are probably plenty of extensions or 3rd party libraries that do this, but it’s pretty easy to achieve with a it of reflection.
Consider the case where I’m specifying bindings of my base repository and services. My BaseRepository<T> implements by IRepository<T>. Then, my specific Repository inherits from BaseRepository<T> where the type specification is explicit. It may look like this:
public interface IRepository<T> : IDisposable where T : class { } public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class { } public class SpecificClassRepository : BaseRepository<SpecificClass> { public SpecificClassRepository(oject obj) : base(obj) { } }
With that in mind, imagine that I define hundreds of repositories. The Ninject setup would include a line per class to specify the binding:
kernel.Bind<IRepository<SomeClass1>>().To<SomeClass1Repository>().InRequestScope(); kernel.Bind<IRepository<SomeClass2>>().To<SomeClass2Repository>().InRequestScope(); kernel.Bind<IRepository<SomeClass3>>().To<SomeClass3Repository>().InRequestScope(); kernel.Bind<IRepository<SomeClass4>>().To<SomeClass4Repository>().InRequestScope(); .. etc
That’s pretty tedious boiler plate. Also, if I add new repositories, I have to update my bindings. Here’s where Reflection comes in and all of that binding code can be reduced to (2) lines:
foreach (var type in Assembly.GetAssembly(typeof(IRepository<>)).GetTypes().Where(x => x.IsClass && x.BaseType != null && x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<>)).ToList()) kernel.Bind(type.GetInterfaces().FirstOrDefault()).To(type).InRequestScope();
Basically, all we’re doing here is querying the assembly which contains our IRepository<> and then querying for any classes that are inherited from a base class where the base class is a generic type and the generic type definition is BaseRepository<>. This is pretty specific and prevents most any side effect. With those types in hand, we get their first interface, which should be IRepository<SpecificClass>, and bind it to the the specific repository type.
I also have a Domain project which contains many services which implement specific interfaces. We can expand our automatic binding a bit further to bind any classes that implement an interface to that interface type.
var assembly = Assembly.GetAssembly(typeof(BaseService)); var types = assembly.GetTypes().Where(x => x.IsClass && x.GetInterfaces().Any()).ToList(); foreach (var type in types) { var interfaceType = type.GetInterfaces().FirstOrDefault(); kernel.Bind(interfaceType).To(type).InRequestScope(); }
This code is the same as the previous bit of code, but is more verbose. Obviously, it could be reduced to two lines as the other example is. Again, we get the types from the assembly containing our services where the types are classes and the classes implement any interface. Then, we bind the first interface specified by the class’s interface to the class type.
I’m pretty pleased with this approach as it reduces each of my 75+ single binding expressions in one project to only (4) lines of code. Also, if I add new repositories or services, they are automatically bound.