This feature would be really nice to have. A similar feature exists in ADO.net Datatables. It would be really helpful for LinqToSql as well. Sure you would lose strongly typed checking, but thats the whole point, you want dynamic searches. If you handle the exceptions properly I really think its a feature worth having.
You might consider adding a feature request to Microsoft Connect. The library already exists maybe they will consider adding official support for it. If you do make a feature request make sure you post a link here so we can vote for it. Microsoft Connect has voting system similar to stackoverflow. I have submitted a few myself LinqtoSql TableUpdate and VB.net Readonly Interfaces like C#.
I remember having some trouble with this library. I think it had something to do with static methods.
I found it better to develop the expressions I needed. This article by Ilya Builuk demonstrates custom expressions. The nice thing about Ilya's framework it removes a lot of the boilerplate code when doing operations like sorting for jqGrid.
I found it extremely helpful when learning about the underlying concepts of expressions.
The nice thing about this code is that it allows you to use dot operators for getters. Person.Age
or if you want to violate Demeter you can even do multiple getters.
The code can be improved upon. I believe I added StartsWith
and only allowed it for string operations as well as a few other search operations. Regardless its worth a look, it helped me understand linq expressions a lot.
public static IQueryable<T> Where<T>(this IQueryable<T> query, string column, object value, WhereOperation operation)
{
if (string.IsNullOrEmpty(column))
return query;
ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");
MemberExpression memberAccess = null;
foreach (var property in column.Split('.'))
memberAccess = MemberExpression.Property
(memberAccess ?? (parameter as Expression), property);
//change param value type
//necessary to getting bool from string
ConstantExpression filter = Expression.Constant
(
Convert.ChangeType(value, memberAccess.Type)
);
//switch operation
Expression condition = null;
LambdaExpression lambda = null;
switch (operation)
{
//equal ==
case WhereOperation.Equal:
condition = Expression.Equal(memberAccess, filter);
lambda = Expression.Lambda(condition, parameter);
break;
//not equal !=
case WhereOperation.NotEqual:
condition = Expression.NotEqual(memberAccess, filter);
lambda = Expression.Lambda(condition, parameter);
break;
//string.Contains()
case WhereOperation.Contains:
condition = Expression.Call(memberAccess,
typeof(string).GetMethod("Contains"),
Expression.Constant(value));
lambda = Expression.Lambda(condition, parameter);
break;
}
MethodCallExpression result = Expression.Call(
typeof(Queryable), "Where",
new[] { query.ElementType },
query.Expression,
lambda);
return query.Provider.CreateQuery<T>(result);
}
WhereOperation enumerator:
public enum WhereOperation { Equal, NotEqual, Contains }