ExpressionExtend
using System.Linq.Expressions;
using System.Reflection;
namespace CustCommon.Extends;
/// <summary>
/// 表达式扩展方法
/// </summary>
public static class ExpressionExtend
{
/// <summary>
/// 根据集合构建 or 表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="paramList">查询条件集合</param>
/// <param name="format">格式化条件</param>
/// <param name="fieldName">db字段名</param>
/// <returns></returns>
public static Expression<Func<T, bool>> BuilderOr<T>(this List<string> paramList, string format, string fieldName)
{
// 如果参数集合为空 或 格式化字符串为空,直接返回null
if (paramList.IsNullOrEmpty() || format.CustIsNullOrWhiteSpace()) return null;
// 构建动态表达式: x.FieldName.Contains($",{code},") 任意一个满足即可
Expression<Func<T, bool>> itemExpression = null;
// {x}
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
// {x.FieldName}
MemberExpression itemKeysProperty = Expression.Property(parameter, fieldName);
foreach (var code in paramList)
{
// 构建常量: $",{code},"
ConstantExpression value = Expression.Constant(string.Format(format, code));
// 构建方法调用: {Boolean Contains(System.String)}
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
// {x.FieldName.Contains(",25,")}
MethodCallExpression containsCall = Expression.Call(itemKeysProperty, containsMethod, value);
// 转换为Lambda表达式: {x => x.FieldName.Contains(",25,")}
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(containsCall, parameter);
// 组合为OR条件
if (itemExpression == null)
// {x => x.FieldName.Contains(",25,")}
itemExpression = lambda;
else
// {x => (x.FieldName.Contains(",25,") OrElse x.FieldName.Contains(",27,"))}
itemExpression = itemExpression.Or(lambda);
}
// 最终表达式: {x => (x.FieldName.Contains(",25,") OrElse x.FieldName.Contains(",27,"))}
return itemExpression;
}
/// <summary>
/// 组合两个表达式为OR关系
/// </summary>
public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> left,
Expression<Func<T, bool>> right)
{
var visitor = new ParameterRebinder(right.Parameters[0], left.Parameters[0]);
var rightBody = visitor.Visit(right.Body);
return Expression.Lambda<Func<T, bool>>(
Expression.OrElse(left.Body, rightBody),
left.Parameters);
}
private class ParameterRebinder : ExpressionVisitor
{
private readonly ParameterExpression _oldParam;
private readonly ParameterExpression _newParam;
public ParameterRebinder(ParameterExpression oldParam, ParameterExpression newParam)
{
_oldParam = oldParam;
_newParam = newParam;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node == _oldParam ? _newParam : base.VisitParameter(node);
}
}
}
调用
var itemLamda = list.BuilderOr<TableName>(",{0},", "FieldName");