views:

103

answers:

2

I'm refactoring all my repository interfaces of various types. Most of them contain very similar methods like Add, Update but some have methods which only makes sense for a specific type. This is a best practices question.

I thought about using generics to straighten things up.

 public interface IRepository<T>
 {
      T Get(int id);
      void Add(T x);
 }

But now for the specific methods. I could ofcourse "subclass" the interface, but then I'm not better off than before. I would have code like:

 IUserRepository<User> users;

One neat way would be if I could have multiple constraints like:

 public partial interface IRepository<T>
 {
      T Get(int id);
      void Add(T x);
 }

 public partial interface IRepository<T> where T: User
 {
      T Get(Guid id);
 }

 public partial interface IRepository<T> where T: Order
 {
      T Get(string hash);
 }

But the compiler complains about conflicting inheritance. Annother way would be contraints on the methods:

 public partial interface IRepository<T>
 {
      T Get(int id);
      void Add(T x);

      T Get(Guid id) where T: User;
      T Get(string hash) where T: Order;
 }

But that's not quite the way these this work is it. Compiler fathoms not my intentions and wants a type definition on the method, of course.

Right now I just have methods that throw NotImplemented. Ugly.

I'm looking for a solution that will make me kick myself.

+5  A: 
public interface IRepository<TEntity, TId>
 {
      TEntity Get(TId id);
      void Add(T x);
 }

public class UserRepository : IRepository<User, Guid>
{
    public User Get( Guid id ) 
    {
        // ...
    }

    public void Add( User entity) 
    {
        // ...
    }
}

public class OrderRepository : IRepository<Order, string> 
{
    //...
}
BioBuckyBall
I assume defining the methods was unintentional. Any other ideas, anyone?
Martin
oops, right you are....fixed
BioBuckyBall
Not perfect. I can implement IRepository<Order,Guid> which dosn't make any sense. Plus it's gonna be a long type list. So for that reason I actually prefer "subinterfacing" as IUserRepository : IRepository<User>.
Martin
+1  A: 

Here are my thoughts on a similar question:

http://stackoverflow.com/questions/1230571/advantage-of-creating-a-generic-repository-vs-specific-repository-for-each-objec/1231473#1231473

The gist is that domains often can't be generalized, and another approach is in order. I give an example of using domain-specific interfaces but with a generalized base class.

Bryan Watts