Since the pattern originates in Domain Driven Design, here's a DDD answer :
The contract of a Repository is usually defined in the Domain layer. This allows objects in the Domain and Application layers to manipulate abstractions of Repositories without caring about their real implementation and the underlying storage details - in other words, to be persistence-ignorant. Besides, we often want specific behaviors to be included in the contracts of some repositories (in addition to your vanilla Add(), GetById(), etc.) so I prefer the ISomeEntityRepository
form than just IRepository<SomeEntity>
- we'll see why they need to be interfaces later.
The concrete implementations of Repositories, on the other hand, reside in the Infrastructure layer (or in the Tests module for test repositories). They implement the above repository contract but also have their own range of persistence-specific characteristics. For instance, if you're using NHibernate to persist your entities, having a superclass to all the NHibernate repositories with the NHibernate session and other NHibernate-related generic plumbing in it could come in handy.
Since you can't inherit several classes, one of these 2 things that your final concrete Repository inherits has to be an interface.
It's more logical for the Domain layer contract to be an interface (ISomeEntityRepository
) since it's a purely declarative abstraction and mustn't make any assumption about what underlying persistence mechanism will be used - i.e. it mustn't implement anything.
The persistence-specific one can be an abstract class (NHibernateRepository
or NHibernateRepository<T>
in the Infrastructure layer) which allows you to centralize there some behaviors that are common to the whole range of persistent-store-specific repositories that will exist.
This results in something like :
public class SomeEntityRepository : NHibernateRepository<SomeEntity>, ISomeEntityRepository
{
//...
}