views:

52

answers:

2

I have an Interface

 interface IRepository<T>
 {
     List<T> GetAll(string id)
     List<T> GetAll(string id, string desc)
     List<T> GetAll(string id, string desc, int[] status)
     List<T> GetAll(string id, string desc, int[] status, ....)
 }

Many of my classes were implementing this interface. My problem is, more often, when clients request customization, I usually need to add parameters on the methods. So when I have 10 classes implementing this interface, i also need to update each of the classes inherinting the interface (I'm using abstract factory pattern) which is quite hassle. And it also not very pleasing to the eye seeing many method overloading like the example above, imo. Is there any solution/work around to make the parameters dynamic (beside to the param [] option which I don't like). I mean like a dedicated class/interface parameter so that i dont need to overload the method when i'm adding parameter. SOmething like this

  interface IRepository<T>
  {
     List<T> GetAll(Parameter args);
  }

the Paramter class (or maybe interface)

  static class Parameter
  {
     public string Id { get; set; }
     public string Desc { get; set; }
     public int[] Status { get; set; }
  }

sample implementation by clients

  class Client1Accounts : IRepository<Employee>
  {
      List<Employee> GetALl(Parameter param)
      {
           return DataFactory.GetAllById(param.Id);
       }   
  }

  class Client2Accounts : IRepository<Employee>
  {
      List<Employee> GetALl(Parameter param)
      {
           return DataFactory.GetAllByDesc(param.Desc);
       }   
  }


  class Client2Accounts : IRepository<Employee>
  {
      List<Employee> GetALl(Parameter param)
      {
           int[] status = { 99, 88 }
           return DataFactory.GetAllFiltered(param.Id, param.Desc, status);
       }   
  }

In this way, when I need to add parameter, I'll just have to add another property to the Parameter Class

  static class Parameter
  {
     public string Id { get; set; }
     public string Desc { get; set; }
     public int[] Status { get; set; }
     public long newLongParam { get; set; }
  }

Is this approach correct? any other ideas?

+1  A: 

It feels to me like the repositories wouldn't really be implementing the interface in its full spirit if they only used part of the parameter, ignoring the rest. In some cases that makes sense, but it doesn't look like it in this situation.

The point of an interface is that the caller shouldn't need to care what the implementation is like - it can treat each implementation the same way.

It looks like a caller given an instance of Client1Accounts would be pretty confused if they tried to search by description, only to find the description was completely ignored, for example.

If different callers really need to search by different things, is the single interface really giving you much value?

The "introduce a new type for a parameter" idea is fine in itself - but I think that when applied to this design, it's going to bite you in the long run.

(If you're interested in the "introduce a new type" pattern, there are examples in the framework - ProcessStartInfo possibly being the best one I can think of immediately.)

Jon Skeet
Maybe i dont need to have an interface for this, but what is your suggestion, in this case, clientA can pass only the ID and clientB can pass only the Desc, yet they both WANT the same, get the same data? thanks ^^
CSharpNoob
@CSharpNoob: They both want to get the same data, but if different clients can pass different types of data then any *proper* implementation would have to cope with *all* those requests... the examples you've given would only cope with particular kinds of caller. That's not the way interfaces are meant to work.
Jon Skeet
A: 

How about this:

public interface IRepository<T>
{
    IQueryable<T> GetAll();
}
Darin Dimitrov
can you give me sample implementation of this? how can this interface address my problem? sorry I havent use this interface yet.. thanks
CSharpNoob
Modern ORMs such as NHibernate and Linq to Entities provide sample implementations of this interface allowing you to translate queries to SQL. They return a lazy result set which could then be filtered based on different criteria.
Darin Dimitrov