using System; using System.Linq.Expressions; using System.Text; public static class ExpressionExtensions { public static string ToReadableString(this Expression expression) { if (expression == null) return string.Empty; var builder = new StringBuilder(); BuildReadableString(expression, builder); return builder.ToString(); } private static void BuildReadableString(Expression expression, StringBuilder builder) { switch (expression) { case LambdaExpression lambda: BuildReadableString(lambda.Body, builder); break; case BinaryExpression binary: builder.Append("("); BuildReadableString(binary.Left, builder); builder.Append($" {GetOperator(binary.NodeType)} "); BuildReadableString(binary.Right, builder); builder.Append(")"); break; case MemberExpression member: builder.Append(member.Member.Name); break; case ParameterExpression parameter: builder.Append(parameter.Name); break; case ConstantExpression constant: builder.Append(constant.Value); break; case MethodCallExpression methodCall: builder.Append(methodCall.Method.Name); builder.Append("("); for (int i = 0; i < methodCall.Arguments.Count; i++) { BuildReadableString(methodCall.Arguments[i], builder); if (i < methodCall.Arguments.Count - 1) builder.Append(", "); } builder.Append(")"); break; default: builder.Append(expression.ToString()); break; } } private static string GetOperator(ExpressionType nodeType) => nodeType switch { ExpressionType.Add => "+", ExpressionType.Subtract => "-", ExpressionType.Multiply => "*", ExpressionType.Divide => "/", ExpressionType.AndAlso => "&&", ExpressionType.OrElse => "||", ExpressionType.Equal => "==", ExpressionType.NotEqual => "!=", ExpressionType.LessThan => "<", ExpressionType.LessThanOrEqual => "<=", ExpressionType.GreaterThan => ">", ExpressionType.GreaterThanOrEqual => ">=", _ => nodeType.ToString() }; }
With expanded methods:
using System; using System.Linq.Expressions; using System.Text; public static class ExpressionExtensions { public static string ToReadableString(this Expression expression) { if (expression == null) return string.Empty; var builder = new StringBuilder(); BuildReadableString(expression, builder); return builder.ToString(); } private static void BuildReadableString(Expression expression, StringBuilder builder) { switch (expression) { case LambdaExpression lambda: BuildReadableString(lambda.Body, builder); break; case BinaryExpression binary: builder.Append("("); BuildReadableString(binary.Left, builder); builder.Append($" {GetOperator(binary.NodeType)} "); BuildReadableString(binary.Right, builder); builder.Append(")"); break; case MemberExpression member: builder.Append(member.Member.Name); break; case ParameterExpression parameter: builder.Append(parameter.Name); break; case ConstantExpression constant: builder.Append(constant.Value); break; case MethodCallExpression methodCall: if (methodCall.Method.DeclaringType == typeof(Enumerable) || methodCall.Method.DeclaringType == typeof(Queryable)) { // LINQ-methoden zoals Where, Any, etc. TranslateLinqMethod(methodCall, builder); } else { // Andere method calls builder.Append(methodCall.Method.Name); builder.Append("("); for (int i = 0; i < methodCall.Arguments.Count; i++) { BuildReadableString(methodCall.Arguments[i], builder); if (i < methodCall.Arguments.Count - 1) builder.Append(", "); } builder.Append(")"); } break; default: builder.Append(expression.ToString()); break; } } private static void TranslateLinqMethod(MethodCallExpression methodCall, StringBuilder builder) { switch (methodCall.Method.Name) { case "Where": builder.Append("Filter items where "); var lambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(lambda.Body, builder); break; case "Any": builder.Append("Exists where "); var anyLambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(anyLambda.Body, builder); break; case "All": builder.Append("All items satisfy "); var allLambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(allLambda.Body, builder); break; case "Select": builder.Append("Select "); var selectLambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(selectLambda.Body, builder); break; case "OrderBy": builder.Append("Order by "); var orderByLambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(orderByLambda.Body, builder); break; case "OrderByDescending": builder.Append("Order by descending "); var orderByDescLambda = (LambdaExpression)((UnaryExpression)methodCall.Arguments[1]).Operand; BuildReadableString(orderByDescLambda.Body, builder); break; default: builder.Append(methodCall.Method.Name); builder.Append("("); for (int i = 0; i < methodCall.Arguments.Count; i++) { BuildReadableString(methodCall.Arguments[i], builder); if (i < methodCall.Arguments.Count - 1) builder.Append(", "); } builder.Append(")"); break; } } private static string GetOperator(ExpressionType nodeType) => nodeType switch { ExpressionType.Add => "+", ExpressionType.Subtract => "-", ExpressionType.Multiply => "*", ExpressionType.Divide => "/", ExpressionType.AndAlso => "&&", ExpressionType.OrElse => "||", ExpressionType.Equal => "==", ExpressionType.NotEqual => "!=", ExpressionType.LessThan => "<", ExpressionType.LessThanOrEqual => "<=", ExpressionType.GreaterThan => ">", ExpressionType.GreaterThanOrEqual => ">=", _ => nodeType.ToString() }; }
914300cookie-checkConvert LINQ expression to readable string