1
votes

I have three projects

  • Application.Infrastructure
  • Application.A (has reference from Application.Infrastructure)
  • Application.B (has reference from Application.Infrastructure)
  • Application.Web (has reference from all)

In Application.Infrastructure i have a generic repository class

public interface IRepository<T>
{
    T FirstOrDefault(Expression<Func<T, bool>> where);
}

In Application.A i have an implementation of this repository

public class ApplicationARepository<T> : IRepository<T>
{
    private readonly IApplicationADBContext _context;
    public ApplicationARepository(IApplicationADBContext context)
    {
        _context = context;
    }
    // implementation
}

In Application.B i have another implementation of the repository interface

public class ApplicationBRepository<T> : IRepository<T>
{
    private readonly IApplicationBDBContext _context;
    public ApplicationBRepository(IApplicationBDBContext context)
    {
        _context = context;
    }
    // implementation
}

In Application.Web i bind the interfaces using Ninject

// Bind implementations from Application.A
kernel.Bind<IApplicationADBContext>().To<ApplicationADBContext>().InRequestScope();
kernel.Bind(typeof(IRepository<>)).To(typeof(ApplicationARepository<>));

// Bind implementations from Application.B
kernel.Bind<IApplicationBDBContext>().To<ApplicationBDBContext>().InRequestScope();

// Here should fail. I already binded typeof(IRepository<>) to typeof(ApplicationARepository<>)
kernel.Bind(typeof(IRepository<>)).To(typeof(ApplicationBRepository<>));

Even if i bind the same interface to two different types, without specifying any .Where() clause, it is working and i don't get any errors.

Why? How Ninject knows how to differentiate them?

1
What line of code do you expect to fail? The second binding or the line where you try to resolve the interface?Adam Houldsworth
The interfaces are different.. BDB and ADB ...Simon Whitehead
the second binding when i bind the same interface to another typeCatalin
You mean the repositories? Take out the contexts from your example.. it's confusing :(Simon Whitehead
Check this article, I think this explains why/how it works github.com/ninject/ninject/wiki/Multi-injection.sTodorov

1 Answers

0
votes

It is absolutely correct to bind multiple implementations to single interface. You can then let Ninject to inject them as an IEnumerable. You can even bind one implementation multiple times.

For example:

// binding
kernel.Bind<IService>().To<BasicService>();
kernel.Bind<IService>().To<BasicService>();

// injection
private IEnumerable<IService> myServices;

public NeedServices(IEnumerable<IService> myServices)
{
     this.myServices = myServices;
}

And you will get a collection of two references to BasicService.

The case, where you will get an error, would be if you would try to inject a single implementation. The error will raise when Ninject tries to resolve the dependency (and he does not know which implementation to choose).

public NeedService(IService myService)
{
     this.myService = myService;
}

So the resolution is that Ninject does not check if dependencies could be resolved at the time of binding, but at the time when injection should occur.

And it perfectly make sense, because conditions for some kinds of Contextual-Binding could change in time (e.g. if your using .When(x=> ItIsRightTimeToInjectAImplementation()).