static void Path(PathInfo info, Expression expr, Expression path) { #if DEBUG _callCounter1++; #endif if (expr == null) { return; } switch (expr.NodeType) { case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.ArrayIndex: case ExpressionType.Assign: case ExpressionType.Coalesce: case ExpressionType.Divide: case ExpressionType.Equal: case ExpressionType.ExclusiveOr: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.LeftShift: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.Modulo: case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.NotEqual: case ExpressionType.Or: case ExpressionType.OrElse: case ExpressionType.Power: case ExpressionType.RightShift: case ExpressionType.Subtract: case ExpressionType.SubtractChecked: { path = ConvertTo(path, typeof(BinaryExpression)); Path(info, ((BinaryExpression)expr).Conversion, Expression.Property(path, ReflectionHelper.Binary.Conversion)); Path(info, ((BinaryExpression)expr).Left, Expression.Property(path, ReflectionHelper.Binary.Left)); Path(info, ((BinaryExpression)expr).Right, Expression.Property(path, ReflectionHelper.Binary.Right)); break; } case ExpressionType.ArrayLength: case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.Negate: case ExpressionType.NegateChecked: case ExpressionType.Not: case ExpressionType.Quote: case ExpressionType.TypeAs: case ExpressionType.UnaryPlus: Path( info, ((UnaryExpression)expr).Operand, path = ConvertTo(path, typeof(UnaryExpression)), ReflectionHelper.Unary.Operand); break; case ExpressionType.Call: { path = ConvertTo(path, typeof(MethodCallExpression)); Path(info, ((MethodCallExpression)expr).Object, path, ReflectionHelper.MethodCall.Object); Path(info, ((MethodCallExpression)expr).Arguments, path, ReflectionHelper.MethodCall.Arguments); break; } case ExpressionType.Conditional: { path = ConvertTo(path, typeof(ConditionalExpression)); Path(info, ((ConditionalExpression)expr).Test, path, ReflectionHelper.Conditional.Test); Path(info, ((ConditionalExpression)expr).IfTrue, path, ReflectionHelper.Conditional.IfTrue); Path(info, ((ConditionalExpression)expr).IfFalse, path, ReflectionHelper.Conditional.IfFalse); break; } case ExpressionType.Invoke: { path = ConvertTo(path, typeof(InvocationExpression)); Path(info, ((InvocationExpression)expr).Expression, path, ReflectionHelper.Invocation.Expression); Path(info, ((InvocationExpression)expr).Arguments, path, ReflectionHelper.Invocation.Arguments); break; } case ExpressionType.Lambda: { path = ConvertTo(path, typeof(LambdaExpression)); Path(info, ((LambdaExpression)expr).Body, path, ReflectionHelper.LambdaExpr.Body); Path(info, ((LambdaExpression)expr).Parameters, path, ReflectionHelper.LambdaExpr.Parameters); break; } case ExpressionType.ListInit: { path = ConvertTo(path, typeof(ListInitExpression)); Path(info, ((ListInitExpression)expr).NewExpression, path, ReflectionHelper.ListInit.NewExpression); Path(((ListInitExpression)expr).Initializers, path, ReflectionHelper.ListInit.Initializers, (ex, p) => Path(info, ex.Arguments, p, ReflectionHelper.ElementInit.Arguments)); break; } case ExpressionType.MemberAccess: Path( info, ((MemberExpression)expr).Expression, path = ConvertTo(path, typeof(MemberExpression)), ReflectionHelper.Member.Expression); break; case ExpressionType.MemberInit: { void Modify(MemberBinding b, Expression pinf) { switch (b.BindingType) { case MemberBindingType.Assignment: Path( info, ((MemberAssignment)b).Expression, ConvertTo(pinf, typeof(MemberAssignment)), ReflectionHelper.MemberAssignmentBind.Expression); break; case MemberBindingType.ListBinding: Path( ((MemberListBinding)b).Initializers, ConvertTo(pinf, typeof(MemberListBinding)), ReflectionHelper.MemberListBind.Initializers, (p, psi) => Path(info, p.Arguments, psi, ReflectionHelper.ElementInit.Arguments)); break; case MemberBindingType.MemberBinding: Path( ((MemberMemberBinding)b).Bindings, ConvertTo(pinf, typeof(MemberMemberBinding)), ReflectionHelper.MemberMemberBind.Bindings, Modify); break; } } path = ConvertTo(path, typeof(MemberInitExpression)); Path(info, ((MemberInitExpression)expr).NewExpression, path, ReflectionHelper.MemberInit.NewExpression); Path(((MemberInitExpression)expr).Bindings, path, ReflectionHelper.MemberInit.Bindings, Modify); break; } case ExpressionType.New: Path( info, ((NewExpression)expr).Arguments, path = ConvertTo(path, typeof(NewExpression)), ReflectionHelper.New.Arguments); break; case ExpressionType.NewArrayBounds: Path( info, ((NewArrayExpression)expr).Expressions, path = ConvertTo(path, typeof(NewArrayExpression)), ReflectionHelper.NewArray.Expressions); break; case ExpressionType.NewArrayInit: Path( info, ((NewArrayExpression)expr).Expressions, path = ConvertTo(path, typeof(NewArrayExpression)), ReflectionHelper.NewArray.Expressions); break; case ExpressionType.TypeIs: Path( info, ((TypeBinaryExpression)expr).Expression, path = ConvertTo(path, typeof(TypeBinaryExpression)), ReflectionHelper.TypeBinary.Expression); break; case ExpressionType.Block: { path = ConvertTo(path, typeof(BlockExpression)); Path(info, ((BlockExpression)expr).Expressions, path, ReflectionHelper.Block.Expressions); Path(info, ((BlockExpression)expr).Variables, path, ReflectionHelper.Block.Variables); // ? break; } case ExpressionType.Constant: { path = ConvertTo(path, typeof(ConstantExpression)); if (((ConstantExpression)expr).Value is IQueryable iq && !info.Visited.Contains(iq.Expression)) { info.Visited.Add(iq.Expression); Expression p = Expression.Property(path, ReflectionHelper.Constant.Value); p = ConvertTo(p, typeof(IQueryable)); Path(info, iq.Expression, p, ReflectionHelper.QueryableInt.Expression); } break; } case ExpressionType.Parameter: path = ConvertTo(path, typeof(ParameterExpression)); break; case ExpressionType.Extension: { if (expr.CanReduce) { expr = expr.Reduce(); Path(info, expr, path); } break; } } info.Func(expr, path); }