Simplify NinjectWebCommon RegisterServices with a Generic Service

932 views Asked by At

I'm using Ninject.MVC3 for my DI.

I have more than 25 dependencies to inject, but my RegisterService now has 25 lines with simlar code like:

private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IClientRepository>().To<ClienteRepository>();
            kernel.Bind<IRegionRepository>().To<RegionRepository>();
            kernel.Bind<IRequestTypeRepository>().To<SolicitudTipoRepository>();
            kernel.Bind<OrdenRepository>().To<OrdenRepository>();
            //Some other references....
        }   

But, is possible create a generic repository (or repository interface) to inherit all my repos and only inject a generic class?

2

There are 2 answers

2
pedrommuller On BEST ANSWER

well one way to do it is doing a query your assemblies by interface and implementation using reflection, you have to define which namespaces you would like to scan something like:

string[] namespaces = { "namespace1", "namespace2", "namespace3", "namespace4" };
//scanning assemblies
List<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(x => x.FullName.Contains("mybasenamespace")).ToList();
            foreach (var reg in assemblies.Select(assembly => (from type in assembly.GetExportedTypes()
                                                               where !type.IsInterface && type.GetInterfaces().Any() && namespaces.Any(n => type.Namespace != null && type.Namespace.Contains(n))
                                                               select new
                                                               {
                                                                   Service = type.GetInterfaces().SingleOrDefault(t => t.Name.Contains(type.Name)),
                                                                   Implementation = type
                                                               })).SelectMany(registrations => registrations.Where(reg => reg.Service != null)))
            {
                //do your registrations by type here kernel.bind etc, etc
            }

that way you are implementing convention over configuration and you'll avoid doing registrations one by one, it could be other ways but this strategy can be applied to any container you want to use.

0
Zak Willis On

This allows you to use the generic repository pattern.

kernel.Bind(typeof(ICacheRepository<>)).To(typeof(ICacheRepository<>)).InRequestScope();  

Inside a controller, you need to specify the exact generic type, such as

protected ICacheRepository<MockDataSetEnum> LocalCache;

public PlayAreaController(ICacheRepository<MockDataSetEnum> LocalCache)
{
    this.LocalCache = LocalCache;
}