Mike Taulty's Blog
Bits and Bytes from Microsoft UK
More Dynamic Queries
Mike Taulty's Blog

Mike's Badges

Follow on Twitter
View mike's profile on slideshare
Add to Technorati Favorites
CW Blog Awards

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 :-)


Posted Mon, Jun 18 2007 5:08 AM by mtaulty

Comments

Mike Taulty's Blog wrote Messing with Dynamic LINQ Queries
on Thu, Sep 11 2008 9:08 AM
Mike was chatting to me about how you'd take something like this ( against LINQ to SQL and the Northwind...
(C) Mike Taulty, 2009. All rights reserved. The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems