要检查两个Expression <Func <T,bool >>是否相同,可以使用以下方法:
以下是示例代码:
public static bool AreExpressionsEqual<T>(Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
// 方法1:将两个Expression <Func <T,bool >>转换为字符串表示形式,然后比较字符串是否相同。
string str1 = expr1.ToString();
string str2 = expr2.ToString();
if (str1 == str2)
{
return true;
}
// 方法2:使用ExpressionVisitor类来递归地比较两个Expression <Func <T,bool >>的节点是否相同。
ExpressionEqualityVisitor visitor = new ExpressionEqualityVisitor();
if (visitor.Equals(expr1, expr2))
{
return true;
}
// 方法3:使用ExpressionEqualityComparer类来比较两个Expression <Func <T,bool >>是否相同。
ExpressionEqualityComparer comparer = new ExpressionEqualityComparer();
if (comparer.Equals(expr1, expr2))
{
return true;
}
return false;
}
public class ExpressionEqualityVisitor : ExpressionVisitor
{
private readonly Stack<Expression> _expressions = new Stack<Expression>();
public bool Equals(Expression x, Expression y)
{
_expressions.Clear();
_expressions.Push(x);
_expressions.Push(y);
return Visit(x, y);
}
protected override bool Visit(Expression x, Expression y)
{
if (x == null && y == null)
{
return true;
}
if (x == null || y == null || x.NodeType != y.NodeType || x.Type != y.Type)
{
return false;
}
switch (x.NodeType)
{
case ExpressionType.Negate:
case ExpressionType.NegateChecked:
case ExpressionType.Not:
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
case ExpressionType.ArrayLength:
case ExpressionType.Quote:
case ExpressionType.TypeAs:
case ExpressionType.UnaryPlus:
return VisitUnary((UnaryExpression)x, (UnaryExpression)y);
case ExpressionType.Add:
case ExpressionType.AddChecked:
case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
case ExpressionType.Divide:
case ExpressionType.Modulo:
case ExpressionType.And:
case ExpressionType.AndAlso:
case ExpressionType.Or:
case ExpressionType.OrElse:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.Coalesce:
case ExpressionType.ArrayIndex:
case ExpressionType.RightShift:
case ExpressionType.LeftShift:
case ExpressionType.ExclusiveOr:
return VisitBinary((BinaryExpression)x, (BinaryExpression)y);
case ExpressionType.TypeIs:
return VisitTypeIs((TypeBinaryExpression)x, (TypeBinaryExpression)y);
case ExpressionType.Conditional:
return VisitConditional((ConditionalExpression)x, (ConditionalExpression)y);
case ExpressionType.Constant:
return VisitConstant((ConstantExpression)x, (ConstantExpression)y);
case ExpressionType.Parameter:
return VisitParameter((ParameterExpression)x, (ParameterExpression)y);
case ExpressionType.MemberAccess:
return VisitMemberAccess((MemberExpression)x, (MemberExpression)y);
case ExpressionType.Call:
return VisitMethodCall((MethodCallExpression)x, (MethodCallExpression)y);
case ExpressionType.Lambda:
return VisitLambda((LambdaExpression)x, (LambdaExpression)y);
case ExpressionType.New:
return VisitNew((NewExpression)x, (NewExpression)y);
case ExpressionType.MemberInit:
return VisitMemberInit((MemberInitExpression)x, (MemberInitExpression)y);
case ExpressionType.ListInit:
return VisitListInit((ListInitExpression)x, (ListInitExpression)y);
case ExpressionType.NewArrayInit:
case ExpressionType.NewArrayBounds:
return VisitNewArray((NewArrayExpression)x, (NewArrayExpression)y);
case ExpressionType.Invoke:
return VisitInvocation((InvocationExpression)x, (InvocationExpression)y);
case ExpressionType.Index:
return VisitIndex((IndexExpression)x, (IndexExpression)y);
case ExpressionType.Extension:
return VisitExtension(x, y);
default:
throw new NotSupportedException(string.Format("Unhandled expression type: '{0}'", x.NodeType));
}
}
protected override Expression VisitBinary(BinaryExpression x, BinaryExpression y)
{
if (!Equals(x.Method, y.Method))
{
return false;
}
if (!Visit(x.Left, y.Left))
{
return false;
}
if (!Visit(x.Right, y.Right))
{
return false;
}
return true;
}
protected override Expression VisitConditional(ConditionalExpression x, ConditionalExpression y)
{
if (!Visit(x.Test, y.Test))
{
return false;
}
if (!Visit(x.IfTrue, y.IfTrue))
{
return false