【发布时间】:2018-04-06 11:21:49
【问题描述】:
我正在尝试从不同的结构构建表达式树。为方便起见,我们称该结构为 S。我遇到了一个问题。我必须能够从 S 中的图形并基于 S 指定的输入和输出类型构造一个LambdaExpression。 S 指定表达式本身和LambdaExpression 的签名(例如Func<int, int>, Func<bool, string, int> 等)。因为我可以在构建表达式时使用非泛型 Expression.Lambda(...),所以我可以放心地忽略签名。但是当表达式有递归调用时它不起作用。我必须事先将表达式本身存储在Expression.Variable(typeof(Func<...>)) 中以供将来调用。但是我不知道编译时的类型,因为我将 S 作为数据,这完全是运行时的事情。
示例如下:
public class Structure
{
public Parameter[] InputParams { get; set; }
public Parameter OutputParam { get; set; }
public Graph Expression { get; set; }
}
public class Parameter
{
public string Name { get; set; }
public string Type { get; set; }
}
public class Builder
{
public static Expression Build(Structure s)
{
var inputParams = new ParameterExpression[s.InputParams.Length];
int index = 0;
foreach (var param in s.InputParams)
{
inputParams[index++] = Expression.Parameter(Utils.GetDataType(param.Type), param.Name);
}
ParameterExpression delegVar = Expression.Variable(typeof(Func<int, int>), "sum"); // here types of Func must be taken from S
LambdaExpression expression = Expression.Lambda(
Expression.Block(
new[] { delegVar },
Expression.Assign(delegVar,
Expression.Lambda(
Expression.Block(
// some work is done here
Expression.Invoke(delegVar, inputParams)
),
inputParams
)
),
Expression.Invoke(delegVar, inputParams)
),
inputParams
);
return expression;
}
}
请忽略表达式会在运行时抛出 StackOverflowException 的事实。
【问题讨论】:
-
你能否展示一个如何初始化结构的例子?举例说明如何调用
Build()方法。 -
感谢您的回复。但我已经解决了这个问题。我会在这里发布。
标签: c# linq lambda expression-trees