如何正确合并具有不同参数的 lambda 表达式
How to properly merge lambda-expressions with different parameters
我有两个表达方式:
Expression<Func<long, bool>> condition = x => x < max; // Exp # 1
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
condition = Expression.Lambda<Func<long, bool>>(
Expression.AndAlso(condition, limit), condition.Parameters);
}
var comparator = condition.Compile();
while (comparator(k++, n--))
{
// Something
}
下面的代码可以编译,但是它只需要一个 "long" 类型的参数到组合的 lambda 中,我怎样才能将两个不同的参数传递到组合的 lambda 中?
我现在手头没有 Visual Studio,但凭直觉你试过这个看看是否有效:
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
condition = Expression.Lambda<Func<long, int, bool>>(
Expression.AndAlso(condition, limit), condition.Parameters);
}
这将为新组合的 Lambda 提供一个接受两个参数和 returns 布尔值的签名。您可能还需要在 condition.Parameters
之后执行一些操作以将 limit.parameters
也包括在内。
首先,您需要使 condition
具有两个输入的表达式。当不与第二个表达式组合时,将第二个(未使用的)参数添加到 lambda 定义中。组合两个表达式时,在要组合的表达式周围添加 Invoke
。否则,您将收到一个运行时错误,告诉您 Func<int,bool>
和 Func<long,bool>
不能与 &&
运算符组合。
以下是实现方法:
Expression<Func<long,int,bool>> condition;
Expression<Func<long,bool>> exp1 = x => x < max;
if (count > 0)
{
Expression<Func<int,bool>> exp2 = x => x > -1;
condition = Expression.Lambda<Func<long,int,bool>>(
Expression.AndAlso(
Expression.Invoke(exp1, exp1.Parameters)
, Expression.Invoke(exp2, exp2.Parameters)
)
, exp1.Parameters.Concat(exp2.Parameters)
);
} else {
condition = Expression.Lambda<Func<long,int,bool>>(
Expression.Invoke(exp1, exp1.Parameters)
, exp1.Parameters.Concat(new[]{Expression.Parameter(typeof(int))})
);
}
var comparator = condition.Compile();
Expression<Func<long, bool>> condition = x => x < max; // Exp # 1
Expression<Func<long, int, bool>> combined = null;
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
combined = Expression.Lambda<Func<long, int, bool>>(
Expression.And(condition.Body, limit.Body),
new ParameterExpression[]
{
condition.Parameters[0],
limit.Parameters[0]
}
);
} else {
// Count <= 0, `int` parameter will be provided, but `body` ignores it
combined = Expression.Lambda<Func<long, int, bool>>(
condition.Body,
new ParameterExpression[]
{
condition.Parameters[0],
limit.Parameters[0]
}
);
}
// compile `combined` expression
var comparator = combined.Compile();
while (comparator(k++, n--))
{
// Something
}
我有两个表达方式:
Expression<Func<long, bool>> condition = x => x < max; // Exp # 1
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
condition = Expression.Lambda<Func<long, bool>>(
Expression.AndAlso(condition, limit), condition.Parameters);
}
var comparator = condition.Compile();
while (comparator(k++, n--))
{
// Something
}
下面的代码可以编译,但是它只需要一个 "long" 类型的参数到组合的 lambda 中,我怎样才能将两个不同的参数传递到组合的 lambda 中?
我现在手头没有 Visual Studio,但凭直觉你试过这个看看是否有效:
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
condition = Expression.Lambda<Func<long, int, bool>>(
Expression.AndAlso(condition, limit), condition.Parameters);
}
这将为新组合的 Lambda 提供一个接受两个参数和 returns 布尔值的签名。您可能还需要在 condition.Parameters
之后执行一些操作以将 limit.parameters
也包括在内。
首先,您需要使 condition
具有两个输入的表达式。当不与第二个表达式组合时,将第二个(未使用的)参数添加到 lambda 定义中。组合两个表达式时,在要组合的表达式周围添加 Invoke
。否则,您将收到一个运行时错误,告诉您 Func<int,bool>
和 Func<long,bool>
不能与 &&
运算符组合。
以下是实现方法:
Expression<Func<long,int,bool>> condition;
Expression<Func<long,bool>> exp1 = x => x < max;
if (count > 0)
{
Expression<Func<int,bool>> exp2 = x => x > -1;
condition = Expression.Lambda<Func<long,int,bool>>(
Expression.AndAlso(
Expression.Invoke(exp1, exp1.Parameters)
, Expression.Invoke(exp2, exp2.Parameters)
)
, exp1.Parameters.Concat(exp2.Parameters)
);
} else {
condition = Expression.Lambda<Func<long,int,bool>>(
Expression.Invoke(exp1, exp1.Parameters)
, exp1.Parameters.Concat(new[]{Expression.Parameter(typeof(int))})
);
}
var comparator = condition.Compile();
Expression<Func<long, bool>> condition = x => x < max; // Exp # 1
Expression<Func<long, int, bool>> combined = null;
if (count > 0)
{
Expression<Func<int, bool>> limit = x => x > -1; // Exp # 2
combined = Expression.Lambda<Func<long, int, bool>>(
Expression.And(condition.Body, limit.Body),
new ParameterExpression[]
{
condition.Parameters[0],
limit.Parameters[0]
}
);
} else {
// Count <= 0, `int` parameter will be provided, but `body` ignores it
combined = Expression.Lambda<Func<long, int, bool>>(
condition.Body,
new ParameterExpression[]
{
condition.Parameters[0],
limit.Parameters[0]
}
);
}
// compile `combined` expression
var comparator = combined.Compile();
while (comparator(k++, n--))
{
// Something
}