表达树。使用Expression.Variable中的运行时类型存储LambdaExpression

时间:2018-04-05 09:28:34

标签: c# linq lambda expression-trees

我试图从不同的结构构建表达式树。为方便起见,我们称之为结构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的事实。

1 个答案:

答案 0 :(得分:1)

经过在互联网上的广泛搜索后,我终于能够解决问题了。我所做的是创建了一个类型定义,并通过传递类型参数从中创建了泛型类型。这是解决方案。

performSegue(withIdentifier: "segueToMain", sender: self)

编辑:我的解决方案很糟糕。正如Ivan Stoev提到的那样,有一种方法正是为了这个目的。它是Expression.GetFuncType