Reputation: 437
I've got a collection of movies which have various properties (title, release year, rating, etc) that I need to search for using a LINQ query as follows:
public BindingList<Movie> SearchByTitle(string title)
{
var matches = from movies in movieCollection
where movies.Title == title
select movies;
// do some other stuff with the matches
}
But I don't want a separate method to search for each property since the only thing that changes between searches is the where
section. For example where movies.Rating == rating
or where movies.ReleaseYear == releaseYear
. How do I make the search method reusable for all different kinds of searches by passing in some sort of Expression
or Func
as the where
section?
Upvotes: 1
Views: 1233
Reputation: 1502406
How do I make the search method reusable for all different kinds of searches by passing in some sort of Expression or Func as the where section?
Your query really isn't anything other than the where clause. But you can easily make the where part configurable... just not using query expressions.
public BindingList<Movie> SearchByTitle(Expression<Func<Movie, bool>> predicate)
{
var matches = movies.Where(predicate);
// Do common stuff with the matches.
}
EDIT: I was assuming that movies
was an IQueryable<T>
, given that you were talking about Expression
. If it's just an IEnumerable<T>
, you want:
public BindingList<Movie> SearchByTitle(Func<Movie, bool> predicate)
{
var matches = movies.Where(predicate);
// Do common stuff with the matches.
}
Upvotes: 5
Reputation: 4685
You can use an extension method (define this in a static class)
public static IQueryable<T> AddSearchParameter<T>(this IQueryable<T> query, bool condition, System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
if (condition)
{
query = query.Where(predicate);
}
return query;
}
So for example:
public BindingList<Movie> Search(string title, int? year, int? rating)
{
var matches = movieCollection.AddSearchParameter(!string.IsNullorEmpty(title), m=>m.Title == title);
matches = matches.AddSearchParameter(year.HasValue, m=>m.Year == year.Value);
matches = matches.AddSearchParameter(rating.HasValue, m=>m.rating >= rating.Value);
// do some other stuff with the matches
}
If you're using this against a database it will not actually execute the query until you enumerate so this will not make multiple calls to your database.
Upvotes: 1
Reputation: 6914
You could use a CompiledQuery.
Check this very interesting answer on SO.
Hope it helps.
Upvotes: 0