2
votes

I am in the midst of diving into unit testing/dependency injection/mocking. Using Ninject, I can bind an interface to an implementation as follows in my NinjectWebCommon.cs:

kernel.Bind<IRecipeRepository>().To<RecipeRepository>();

and this works fine. However, I don't want to have to individually bind every interface to a concrete implementation. To overcome this, I have used standard naming conventions for interfaces (IFoo is the interface of class Foo) and am trying to use the following to give a default binding to all interfaces using Ninject.Extensions.Conventions. Note: This code lives in the CreateKernel() method in NinjectWebCommon.cs:

kernel.Bind(c => c
        .FromThisAssembly()
        .IncludingNonePublicTypes()
        .SelectAllClasses()
        .BindDefaultInterface()
        .Configure(y => y.InRequestScope()));

However, when I do this, I am receiving the following error:

Error activating IRecipeRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
 2) Injection of dependency IRecipeRepository into parameter recipeRepository of constructor of type RecipesController
 1) Request for RecipesController

All help is appreciated.

Edit: My controller's constructor looks as follows:

    private IRecipeRepository recipeRepository;
    private ISizeRepository sizeRepository;

    [Inject]
    public RecipesController(IRecipeRepository recipeRepository, ISizeRepository sizeRepository)
    {
      this.recipeRepository = recipeRepository;
      this.sizeRepository = sizeRepository;
    }
1
Did it happened while you were trying to run action on that controller or in your tests project? I've just recreated structure like yours and seems to be working fine. Do you have any more information?Mariusz
@Mariusz Willing to supply any wanted information. The error occurs whenever I try to hit any action which uses the controller. I'll update answer to include the controller's contructor also.GregH
@Mariusz also note that my data layer (repositories and EF models) live in a separate project. Could that be the cause?GregH
Answear posted hope it helpsMariusz

1 Answers

1
votes

The reason why you can't bind IRecipeRepository to RecipeRepository is that they are in different assembly than controller. To fix your problem you have to add another binding in NinjectWebCommon.cs. This will work only if interface and concrete classes will be in same assembly:

kernel.Bind(c => c
                .FromAssemblyContaining<IRecipeRepository>()
                .IncludingNonePublicTypes()
                .SelectAllClasses()
                .BindDefaultInterface()
                .Configure(y => y.InRequestScope()));

If concrete implementations and interfaces are in different projects you should replace .FromAssemblyContaining<IRecipeRepository>() to .FromAssemblyContaining<RecipeRepository>() and should work like a charm.