0

I have my UnitOfWork with GetRepository<T> and I need to get it resolved with Ninject.

    public TRepository GetRepository<TRepository>() where TRepository : class, IRepository
    {
        throw new NotImplementedException();
    }

I use MVC and I'm loading my modules in the NinjectWebCommon.cs like that:

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        INinjectModule[] modules = { new CommonModule(), new ServicesModule(), new BusinessModule(), new DataModule() };

        var kernel = new StandardKernel(modules);

        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

Any idea how to get the instance of GetRepository? I've tried creating an IResolver and injecting it into my UnitOfWork and resolving that generic, but I get null.

EDIT:

I would like to update the solution:

    public UnitOfWork(IDbContext context, IKernel resolver)
    {
        _context = context;
        _resolver = resolver;
    }

    public TRepository GetRepository<TRepository>() where TRepository : class, IRepository
    {
        return (TRepository)_resolver.GetService(typeof(TRepository));
    }

Note that I'm using an abstraction and not a concrete implementation of IResolver, so I don't see this as an anti pattern (I might be wrong though). I'm trying to figure out how to solve this using IResolutionRoot as suggested in answer below.

EDIT:

After reading more and more articles I'm of the idea that this is not an anti pattern when working with generics. The only suitable solution to avoid service locator for generics is reflection. So I particularly rather use the service locator than reflection.

DAG
  • 2,460
  • 5
  • 33
  • 61
  • 1
    Did you try to declare an `IKernel` dependency in the constructor? – Yacoub Massad Nov 18 '15 at 14:14
  • That might be a good one. I'll give it a try and let ya know – DAG Nov 18 '15 at 14:40
  • @YacoubMassad that was the solution! GOOD... Thanks – DAG Nov 18 '15 at 18:00
  • @DanielGroh Using an abstraction is not changing the fact that you're relying on the service location to do the lookup for you. Now, i don't want to call it bad programming and i don't want to argue about it (because there sometimes isn't a better solution) but what i think might be wrong with the picture is that you think that adding something (= complexity) is making it any better than it was before. It usually doesn't. IMHO it's usually just the opposite way round. – BatteryBackupUnit Nov 19 '15 at 23:43
  • @BatteryBackupUnit I agree, it has a code smell and I might roll it back. The fact is, there is no service location in my opinion, I'm working with abstraction, I'm not lying on ServiceLocator.GetService(). Please correct if I'm wrong. – DAG Nov 19 '15 at 23:48
  • 1
    how's `return (TRepository)_resolver.GetService(typeof(TRepository));` any different from `ServiceLocator.GetService()`? It being an abstraction usually doesn't help, because over time your abstraction will grow to mimic the container, where it'll not be an abstraction anymore but rather just a thin layer of boiler plate code you could just throw out and replace by direct usage of the container. How much more work is it to replace a container if you don't have a (leaky) abstraction? Very little. – BatteryBackupUnit Nov 19 '15 at 23:53
  • also, even if there's a non-leaky abstraction it's still the Service Locator pattern. Mark seeman would probably recommend an [abstract factory](http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/) instead. Ok he makes a distinction between the service-location being part of the composite-root or not. He thinks if it's part of the composite root it's cleaner (which i agree to some degree - but i also think it doesn't really matter for a lot of projects). – BatteryBackupUnit Nov 19 '15 at 23:55
  • I totally agree, but let's keep concise - this `GetRepository<>` will never change. It pretty much says what it is and I'm able to write unit tests, make mocks and etc... I'm striving to find a better solution, but cannot find. I use a project composition root to load the ninject modules of each project layer. I appreciate such discussions...thank you very much @BatteryBackupUnit and I'll check how abstract factory can help me on this. – DAG Nov 20 '15 at 00:05
  • BTW this [thread](http://stackoverflow.com/questions/6833995/how-to-avoid-service-locator-anti-pattern) pretty much discuss what we just did. good one! – DAG Nov 20 '15 at 00:24

1 Answers1

2

A direct answer to your question is to declare an IKernel (or better, an IResolutionRoot) dependency in the constructor. However, please note that having a dependency on the DI container and usage of this container inside your class is called service location and is considered an anti-pattern. You might want to consider changing the design of this.

Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62