我不确定这是否是严格柯里化(Currying),但我基本上想要实现以下目标。给定一个表达式
:
Expression<Func<T1, T2, TResult>> expression
我想传入一个参数并生成一个相应的表达式
,其中该参数的值是固定的。生成的表达式在功能上应与表达式
等效,只是它应少包含一个参数。
结果表达式看起来像这样:
Expression<Func<T2, TResult>> curriedExpression;
我已经尝试过此操作,但它不起作用,因为 Expression
不会隐式转换为 lambda 表达式:
curriedExpression = b => expression(fixedValueForT1, b);
请注意,curredExpression
不应包含对表达式
的调用;除了固定值之外,它应该包含重复的逻辑。
我希望这是有道理的。如果这含糊不清或解释得不好,请告诉我。
最佳答案
我认为你可以从 ExpressionVisitor
得出以简单的方式上课。这是一个概念证明 - 它可能过于简单化,但我认为这就是您所追求的:
using System;
using System.Linq.Expressions;
class Test
{
static void Main()
{
Expression<Func<int, int, int>> original = (x, y) => MethodX(x) + MethodY(y);
Console.WriteLine("Original: {0}", original);
var partiallyApplied = ApplyPartial(original, 10);
Console.WriteLine("Partially applied: {0}", partiallyApplied);
}
static int MethodX(int x)
{
return x + 1;
}
static int MethodY(int x)
{
return -x;
}
static Expression<Func<T2, TResult>> ApplyPartial<T1, T2, TResult>
(Expression<Func<T1, T2, TResult>> expression, T1 value)
{
var parameter = expression.Parameters[0];
var constant = Expression.Constant(value, parameter.Type);
var visitor = new ReplacementVisitor(parameter, constant);
var newBody = visitor.Visit(expression.Body);
return Expression.Lambda<Func<T2, TResult>>(newBody, expression.Parameters[1]);
}
}
class ReplacementVisitor : ExpressionVisitor
{
private readonly Expression original, replacement;
public ReplacementVisitor(Expression original, Expression replacement)
{
this.original = original;
this.replacement = replacement;
}
public override Expression Visit(Expression node)
{
return node == original ? replacement : base.Visit(node);
}
}
输出:
Original: (x, y) => (MethodX(x) + MethodY(y))
Partially applied: y => (MethodX(10) + MethodY(y))
关于.net - 如何将一个表达式柯里化(Currying)为另一个表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19151810/