Published
Monday, June 18, 2007 5:08 AM
by
mtaulty
Took this slightly further (which you could definitely describe as making it worse :-)) by adding a limited form of an OrElse;
namespace MyExtensions
{
public enum Operand
{
Equal,
NotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual
}
public static class Extensions
{
public static IQueryable<T> AddOrElse<T, V, U>(this IQueryable<T> queryable,
string lhsName, Operand lhsOperand, V lhsValue,
string rhsName, Operand rhsOperand, U rhsValue)
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
IQueryable<T> query = queryable.Where<T>(
Expression.Lambda<Func<T, bool>>(Expression.OrElse(
MakeBinaryExpression<T, V>(pe, lhsName, lhsOperand, lhsValue),
MakeBinaryExpression<T, U>(pe, rhsName, rhsOperand, rhsValue)),
new ParameterExpression[] { pe }));
return (query);
}
public static IQueryable<T> AddClause<T, V>(this IQueryable<T> queryable,
string propertyName, Operand operand, V propertyValue)
{
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
IQueryable<T> query = queryable.Where<T>(
Expression.Lambda<Func<T, bool>>(
MakeBinaryExpression<T, V>(pe, propertyName, operand, propertyValue),
new ParameterExpression[] { pe }));
return (query);
}
private static BinaryExpression MakeBinaryExpression<T, V>(
ParameterExpression parameter, string propertyName, Operand operand, V propertyValue)
{
Func<Expression, Expression, bool, MethodInfo, BinaryExpression>
fn = GetFuncForOperand(operand);
BinaryExpression expression =
fn(Expression.Property(
parameter,
typeof(T).GetProperty(propertyName)),
Expression.Constant(propertyValue, typeof(V)),
false,
null);
return (expression);
}
private static Func<Expression, Expression, bool, MethodInfo, BinaryExpression> GetFuncForOperand(Operand operand)
{
Func<Expression, Expression, bool, MethodInfo, BinaryExpression> func = null;
switch (operand)
{
case Operand.Equal:
func = Expression.Equal;
break;
case Operand.NotEqual:
func = Expression.NotEqual;
break;
case Operand.LessThan:
func = Expression.LessThan;
break;
case Operand.LessThanEqual:
func = Expression.LessThanOrEqual;
break;
case Operand.GreaterThan:
func = Expression.GreaterThan;
break;
case Operand.GreaterThanEqual:
func = Expression.GreaterThanOrEqual;
break;
default:
break;
}
return (func);
}
}
}
and then that can be used as in;
static void Main(string[] args)
{
NorthwindDataContext ctx = new NorthwindDataContext("server=.;database=northwind");
var query = from p in ctx.Products
select p;
int prod = 22;
short? units = 120;
query = query.AddOrElse(
"ProductID", Operand.Equal, prod,
"UnitsInStock", Operand.GreaterThan, units);
foreach (Product v in query)
{
Console.WriteLine(v.ProductID);
}
}
I'm going to stop doing this now - it's making my head hurt :-)