I’m following on from a previous question. The answer I accepted involves using a generic IRepository to handle basic CRUD, wrapped with a domain specific IMovieRepository which delegates to the generic setup. A further detail involves having a WrapQueryInSession method on the generic IRepository:
IEnumerable<T> WrapQueryInSession(Func<ISession, IEnumerable<T>> query);
I was getting to implementation when I realized that this exposes the NHibernate ISession to consumers of the generic repository. NHibernate is otherwise fully contained in the IRepository implementation, but for that method signature.
This comes to the fore when I want to unit test MovieRepository, by having an IRepository, implemented in RepositoryFake, passed to the MovieRepository constructor:
protected override void BeforeEachTest()
{
_fixture = new MovieRepository(new RepositoryFake());
}
My test class has a private fake repository implementation:
private class RepositoryFake : IRepository<Movie>
{
...
public IEnumerable<Movie> WrapQueryInSession(Func<ISession, IEnumerable<Movie>> query)
{
...
}
...
}
The way this is set up, the test class, and any other consumer of an IRepository implementation, is made aware of the ISession from NHibernate, and thus NHibernate itself. This seems a case of a leaky abstraction.
Is there a better way to fully contain use of NHibernate within an IRepository implementation?
The idea from my answer to your previous question was that the generic IRepository is only known inside your infrastructure layer – it is not published outside of this. When you publish the ISession to the non-generic repositories they gain a very versatile interface, as they have access to the ISession for querying. The problem with not exposing the ISession is that your generic repository will either:
Seems a bit of a waste having NHibernate’s querying interface hidden away inside a facade (which the generic Repository would be limited to).
IMO, if you choose nHibernate, you should leverage the power it gives you and live with the dependence through-out your infrastructure dll (including tests). Think of the generic IRepository interface as a helper interface to NHibernate to reduce the amount of duplicate code inside the repositories.