This is more of an academic curiosity but I'm trying to figure out how best to accomplish the following.
Imagine a situation where you have an Person
object
public class Person {
public string Name {get;set;}
public int Age {get;set;}
}
and a Repository Contract for Retrieving them from some persistence store...
public class IPersonRepository {
public IEnumerable<Person> Search(*** SOME_METHOD_SIGNATURE ***);
}
Your consumer application really doesn't care about the specific implementation. It's just gonna grab the correct concrete Implementation from Unity/Ninject & start querying.
IPersonRespository repo = GetConcreteImplementationFromConfig();
repo.Search( ... );
What I'm wondering is what would you use for your Method Signature here that's both flexible & extensible regardless of the implementation.
Option 1.
public IEnumerable<Person> Search(Expression<Func<Person, bool>> expression);
This is nice because if you're using a LINQ Capable (e.g. EntityFramework) data context, you can just pass the expression directly to your context. This option seems to fall down though if you're implementation has to use hand crafted stored procs/sql/ADO.NET etc...
Option 2.
public IEnumerable<Person> Search(PersonSearch parameters);
public class PersonSearch {
public int? Age {get;set;}
public string FullName {get;set;}
public string PartialName { get; set; }
}
This one seems the most flexible (in the sense that it would work with either Linq, Plain Old SQL.
But it just stinks of "Writing your own query language" because you need to account for every possible query the consumer might want to do. e.g. Age >= 18 && Age <=65 && Name LIKE '%John%'
Option 3.
Are there any other options ?