21
votes

I'm fairly new to Ninject, and found myself stumbling when I came to implement a generic repository pattern. I want to bind a dependency IRepository<IEntityType> to a class ConcreteRepository<EntityType> where ConcreteRepository<T> implements IRepository<T> and EntityType implements IEntityType. I tried this:

kernel.Bind<IRepository<IEntityType>>().To<ConcreteRepository<EntityType>>();

...but Ninject won't take that because it doesn't know or care that EntityType implements IEntityType. How can I go about binding this dependency?

UPDATE

This is the error I'm getting:

Error 3 The type 'ICM.Dependency.Repository.ConcreteRepository' cannot be used as type parameter 'TImplementation' in the generic type or method 'Ninject.Syntax.IBindingToSyntax.To()'. There is no implicit reference conversion from 'ConcreteRepository<EntityType>' to 'IRepository<IEntityType>'.

SOLUTION

I still don't quite understand why my binding doesn't work, but evidently I was using generics incorrectly there. As such the solution doesn't really relate to NInject. I ended specifying the ConcreteRepository to explicitly connect IEntityType with TEntityType:

public class ConcreteRepository<TInterface, TEntity> : IRepository<TInterface> where TEntity : TInterface { ... }

Then the injection can be written as follows:

kernel.Bind<IRepository<IEntityType>>().To<ConcreteRepository<IEntityType,EntityType>>()
1
What message are you getting? Is it a compile one or runtime? Does ConcreteRepository<EntityType> implement IRepository<IEntityType> (Also, generally one would have the ctor dependency be on on IRepository<EntityType> - in which case your Bind above would be wrong. - Ruben Bartelink
@RubenBartelink It's a compile error; see update above. To your first point- it does not, but as mentioned ConcreteRepository<T> implements IRepository<T>. Maybe that's my issue. To your second point, I want to use IRepository<IEntityType> in the constructor to allow for flexibility-- the repository dependency should deal with an interface, not concrete entities. - McGarnagle
Right. Well the where constraint that's causing the compile error is there for a reason - there simply is no way in which the concrete component type you're suggesting is going to be convertible to the service type you're Binding to so stop looking! I suggest looking at how others have implmented generic repository patterns - you're far away from normal practice. You could explain what you're getting from this stuff in your question here, but I'd suggest you should ask yourself first and then maybe here whether your class hierarchy can be rationalised. - Ruben Bartelink
@RubenBartelink That's as may be, but my question isn't how to implement a generic repository. It's how to bind a dependency to a generic interface. - McGarnagle
@dbaseman why are you wanting your concrete repository to take a concrete entity at all? couldn't it just take your entity interface? - Not loved

1 Answers

46
votes
kernel.Bind(typeof(IRepository<>)).To(typeof(SimpleRepository<>));

Take a look at my one if you want here: http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html i have binding examples

EDIT:

The error you are getting is saying that your concrete repository isnt an instance of the generic one you want to bind to, ie you will need to do this

public class ConcreteRepository<ConcreteEntity> : IRepository<IEntity>{}

not

public class ConcreteRepository<ConcreteEntity> : IRepository<ConcreteEntity>{}