I need to write some generic Search Method like this:
public List<T> Search<T>(SearchParamsBase searchParams)
{
using (var context = new TestEntities())
{
var dataType = TypeMap.Get(typeof (T));
var dataSet = context.Set(dataType);
var searchQuery = CreateQuery((IEnumerable<object>) dataSet), searchParams)
return searchQuery.ToList()
}
}
and I have a function CreateQuery()
that should filter IEnumerable
object.
This function will be different for all classes. For example:
CreateQuery(IEnumerable<object> collection, SearchParamsBase searchParams)
{
var search = (SomeSearchImplementation)searchParams;
// filter
collection = collection.Where(x => x.Name == search.Name);
// select page
collection = collection.Skip(search.Page * search.CountPerPage);
collection = collection.Take(search.CountPerPage);
// order by and so on
// ...
return collection;
}
How can I implement this idea correctly?
C Introduction C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.
While C and C++ may sound similar, their features and usage differ. C is a procedural programming language that support objects and classes. On the other hand C++ is an enhanced version of C programming with object-oriented programming support.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
What you basically want to do here is construct a LINQ query dynamically. To do this, you need to modify/build the expression tree at runtime. If you are not familiar with expression trees and the Expression<T>
type I recommend this article and the referenced pages in the "See also" section:
http://msdn.microsoft.com/en-us/library/bb397951.aspx
Now that you now the basic concept, let's implement dynamic sorting. The method below is an extension to IQueryable<T>
which means it does not only apply to lists but to every LINQ datasource, so you could also use it directly against a database (which is more efficient when it comes to paging and sorting than in memory operations). The method takes the property name you want to order by and the sort direction (ascending/descending):
public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string sortColumn, bool descending)
{
// Dynamically creates a call like this: query.OrderBy(p => p.SortColumn)
var parameter = Expression.Parameter(typeof(T), "p");
string command = "OrderBy";
if (descending)
{
command = "OrderByDescending";
}
Expression resultExpression = null;
var property = typeof(T).GetProperty(sortColumn);
// this is the part p.SortColumn
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
// this is the part p => p.SortColumn
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
// finally, call the "OrderBy" / "OrderByDescending" method with the order by lamba expression
resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { typeof(T), property.PropertyType },
query.Expression, Expression.Quote(orderByExpression));
return query.Provider.CreateQuery<T>(resultExpression);
}
Now you can write this code to order the dataset by the property Name
in ascending
order:
dataSet.OrderByDynamic("Name", false)
Creating an extension method for dynamic filtering follows the same pattern. If you understand the code above, it won't be a problem for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With