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