Advertisement
Maarten1977

C# Rewriting expression sample

Oct 4th, 2012
403
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.86 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7.  
  8. namespace SomeNamespace {
  9.     public enum CombineOperator { And, Or }
  10.  
  11.     public static class ExpressionRewriter {
  12.         /// <summary>
  13.         /// Combines the specified expression with this one.
  14.         /// </summary>
  15.         /// <typeparam name="TIn">The type of the in.</typeparam>
  16.         /// <param name="expression">The expression.</param>
  17.         /// <param name="anotherExpression">Another expression.</param>
  18.         /// <param name="combineOperator">The combine operator.</param>
  19.         /// <returns></returns>
  20.         public static Expression<Func<TIn, bool>> Combine<TIn>(this Expression<Func<TIn, bool>> expression, Expression<Func<TIn, bool>> anotherExpression, CombineOperator combineOperator) {
  21.             if (combineOperator == CombineOperator.And) {
  22.                 return Expression.Lambda<Func<TIn, bool>>(Expression.AndAlso(expression.Body, anotherExpression.Body), expression.Parameters);
  23.             }
  24.             return Expression.Lambda<Func<TIn, bool>>(Expression.OrElse(expression.Body, anotherExpression.Body), expression.Parameters);
  25.         }
  26.  
  27.  
  28.         /// <summary>
  29.         /// Casts the param of an expression.
  30.         /// </summary>
  31.         /// <typeparam name="TIn">The type of the in.</typeparam>
  32.         /// <typeparam name="TOut">The type of the out.</typeparam>
  33.         /// <param name="inExpr">The in expr.</param>
  34.         /// <returns></returns>
  35.         public static Expression<Func<TOut, bool>> CastParam<TIn, TOut>(Expression<Func<TIn, bool>> inExpr) {
  36.             if (inExpr.NodeType == ExpressionType.Lambda &&
  37.                 inExpr.Parameters.Count > 0) {
  38.  
  39.                 var inP = inExpr.Parameters[0];
  40.                 var outP = Expression.Parameter(typeof(TOut), inP.Name);
  41.  
  42.                 var outBody = Rewrite<TIn, TOut>(
  43.                     inExpr.Body,
  44.                     expr => (expr is ParameterExpression) ? outP : expr
  45.                 );
  46.                 return Expression.Lambda<Func<TOut, bool>>(
  47.                         outBody,
  48.                         new ParameterExpression[] { outP });
  49.             } else {
  50.                 throw new NotSupportedException();
  51.             }
  52.         }
  53.  
  54.         /// <summary>
  55.         /// Rewrites the specified expression.
  56.         /// </summary>
  57.         /// <typeparam name="TIn">The type of the in.</typeparam>
  58.         /// <typeparam name="TOut">The type of the out.</typeparam>
  59.         /// <param name="exp">The exp.</param>
  60.         /// <param name="c">The c.</param>
  61.         /// <returns></returns>
  62.         private static Expression Rewrite<TIn, TOut>(Expression exp, Func<Expression, Expression> c) {
  63.             Expression clone = null;
  64.             var be = exp as BinaryExpression;
  65.             switch (exp.NodeType) {
  66.                 case ExpressionType.AndAlso:
  67.                     clone = Expression.AndAlso(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.Method);
  68.                     break;
  69.                 case ExpressionType.OrElse:
  70.                     clone = Expression.OrElse(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.Method);
  71.                     break;
  72.                 case ExpressionType.Equal:
  73.                     clone = Expression.Equal(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  74.                     break;
  75.                 case ExpressionType.GreaterThan:
  76.                     clone = Expression.GreaterThan(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  77.                     break;
  78.                 case ExpressionType.GreaterThanOrEqual:
  79.                     clone = Expression.GreaterThanOrEqual(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  80.                     break;
  81.                 case ExpressionType.LessThan:
  82.                     clone = Expression.LessThan(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  83.                     break;
  84.                 case ExpressionType.LessThanOrEqual:
  85.                     clone = Expression.LessThanOrEqual(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  86.                     break;
  87.                 case ExpressionType.NotEqual:
  88.                     clone = Expression.NotEqual(Rewrite<TIn, TOut>(be.Left, c), Rewrite<TIn, TOut>(be.Right, c), be.IsLiftedToNull, be.Method);
  89.                     break;
  90.                 case ExpressionType.Not:
  91.                     var ue = exp as UnaryExpression;
  92.                     clone = Expression.Not(Rewrite<TIn, TOut>(ue.Operand, c));
  93.                     break;
  94.                 case ExpressionType.MemberAccess:
  95.                     var me = exp as MemberExpression;
  96.  
  97.                     MemberInfo newMember = me.Member;
  98.                     Type newType = newMember.DeclaringType;
  99.                     if (newType == typeof(TIn)) {
  100.                         newType = typeof(TOut);
  101.                         MemberInfo[] members = newType.GetMember(me.Member.Name);
  102.                         if (members.Length == 1) {
  103.                             newMember = members[0];
  104.                         } else {
  105.                             throw new NotSupportedException();
  106.                         }
  107.                     }
  108.                     clone = Expression.MakeMemberAccess(Rewrite<TIn, TOut>(me.Expression, c), newMember);
  109.                     break;
  110.                 case ExpressionType.Constant:
  111.                     var ce = exp as ConstantExpression;
  112.                     clone = Expression.Constant(ce.Value);
  113.                     break;
  114.                 case ExpressionType.Parameter:
  115.                     var pe = exp as ParameterExpression;
  116.                     Type peNewType = pe.Type;
  117.                     if (peNewType == typeof(TIn)) {
  118.                         peNewType = typeof(TOut);
  119.                     }
  120.                     clone = Expression.Parameter(peNewType, pe.Name);
  121.                     break;
  122.                 case ExpressionType.Call:
  123.                     MethodCallExpression mce = exp as MethodCallExpression;
  124.                     if (mce.Arguments != null && mce.Arguments.Count > 0) {
  125.                         List<Expression> expressionList = new List<Expression>();
  126.                         foreach (Expression expression in mce.Arguments) {
  127.                             expressionList.Add(Rewrite<TIn, TOut>(expression, c));
  128.                         }
  129.                         clone = Expression.Call(Rewrite<TIn, TOut>(mce.Object, c), mce.Method, expressionList.ToArray());
  130.                     } else {
  131.                         clone = Expression.Call(Rewrite<TIn, TOut>(mce.Object, c), mce.Method);
  132.                     }
  133.                     break;
  134.                 case ExpressionType.Invoke:
  135.                     InvocationExpression ie = exp as InvocationExpression;
  136.                     List<Expression> arguments = new List<Expression>();
  137.                     foreach (Expression expression in ie.Arguments) {
  138.                         arguments.Add(Rewrite<TIn, TOut>(expression, c));
  139.                     }
  140.                     clone = Rewrite<TIn, TOut>(ie.Expression, c);
  141.                     //clone = Expression.Invoke(Rewrite<TIn, TOut>(ie.Expression, c), arguments);
  142.                     break;
  143.                 case ExpressionType.Convert:
  144.                     var ue2 = exp as UnaryExpression;
  145.                     //clone = Expression.Not(Rewrite<TIn, TOut>(ue2.Operand, c));
  146.                     clone = Expression.Convert(ue2.Operand, ue2.Type, ue2.Method);
  147.                     break;
  148.                 default:
  149.                     throw new NotImplementedException(exp.NodeType.ToString());
  150.             }
  151.             return c(clone);
  152.         }
  153.     }
  154. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement