.NET中lambda表达式合并问题及解决方法

随心笔谈3年前发布 admin
210 0 0

文章摘要

本文介绍了一个扩展表达式的C#类`ExpressionExtension`,用于合并逻辑与(`AndAlso`)和逻辑或(`OrElse`)的表达式。该类提供了以下功能: 1. `AndAlso`方法:可以将多个表达式合并为一个逻辑与表达式。该方法支持两种实现方式: - 接受一个`IList<Expression<T>>`参数,并通过迭代结合每个表达式。 - 接受两个`Expression<T>`参数,并直接构建逻辑与表达式。 2. `OrElse`方法:可以将多个表达式合并为一个逻辑或表达式。同样支持两种实现方式: - 接受一个`IList<Expression<T>>`参数,并通过迭代结合每个表达式。 - 接受两个`Expression<T>`参数,并直接构建逻辑或表达式。 3. `GetReplaceExpressionVisitor`方法:用于构建一个`ReplaceExpressionVisitor`,该 visitor用于替换旧的参数表达式为新的参数表达式。这通常用于处理参数替换或优化场景。 总结而言,该类通过迭代合并表达式,并提供灵活的实现方式,适用于处理复杂的逻辑与和逻辑或表达式。

 /// <summary>
/// 表达式扩展
/// </summary>
public static class ExpressionExtension
{

/// <summary>
/// 使用AndAlso合并表达式
/// </summary>
/// <param name=”exprs”></param>
/// <returns></returns>
public static Expression<T> AndAlso<T>(this IList<Expression<T>> exprs)
{
if (exprs.Count==0) return null;
if (exprs.Count==1) return exprs[0];

var leftExpr=exprs[0];
var left=leftExpr.Body;
for (int i=1; i < exprs.Count; i++)
{
var expr=exprs[i];
var visitor=GetReplaceExpressionVisitor(expr.Parameters, leftExpr.Parameters);
var right=visitor.Visit(expr.Body);
left=Expression.AndAlso(left, right);
}
return Expression.Lambda<T>(left, leftExpr.Parameters);
}

/// <summary>
/// 使用AndAlso合并表达式
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”left”></param>
/// <param name=”right”></param>
/// <returns>left AndAlso right</returns>
public static Expression<T> AndAlso<T>(this Expression<T> left, Expression<T> right)
{
return AndAlso(new List<Expression<T>>() { left, right });
}

/// <summary>
/// 使用OrElse合并表达式
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”exprs”></param>
/// <returns></returns>
public static Expression<T> OrElse<T>(this IList<Expression<T>> exprs)
{
if (exprs.Count==0) return null;
if (exprs.Count==1) return exprs[0];

var leftExpr=exprs[0];
var left=leftExpr.Body;
for (int i=1; i < exprs.Count; i++)
{
var expr=exprs[i];
var visitor=GetReplaceExpressionVisitor(expr.Parameters, leftExpr.Parameters);
var right=visitor.Visit(expr.Body);
left=Expression.OrElse(left, right);
}
return Expression.Lambda<T>(left, leftExpr.Parameters);
}

/// <summary>
/// 使用OrElse合并表达式
/// </summary>
/// <typeparam name=”T”></typeparam>
/// <param name=”left”></param>
/// <param name=”right”></param>
/// <returns>left OrElse right</returns>
public static Expression<T> OrElse<T>(this Expression<T> left, Expression<T> right)
{
return OrElse(new List<Expression<T>>() { left, right });
}
/// <summary>
/// 构建visitor
/// </summary>
/// <param name=”oldParameters”></param>
/// <param name=”newParameters”></param>
/// <returns></returns>
private static ReplaceExpressionVisitor GetReplaceExpressionVisitor(ReadOnlyCollection<ParameterExpression> oldParameters, ReadOnlyCollection<ParameterExpression> newParameters)
{
Dictionary<Expression, Expression> dic=new Dictionary<Expression, Expression>();
for (int i=0; i < oldParameters.Count; i++)
{
dic.Add(oldParameters[i],newParameters[i]);
}
return new ReplaceExpressionVisitor(dic);
}
}

© 版权声明

相关文章