如何创建这个表达式树(静态方法)

本文关键字:表达式 静态方法 创建 何创建 | 更新日期: 2023-09-27 18:14:11

我想用下面的代码为a => Math.Sin(a)创建一个表达式树对象:

ParameterExpression a = Expression.Parameter(typeof(Double), "a");
MethodCallExpression methodCall = Expression.Call(
    typeof(Math).GetMethod("Sin", BindingFlags.Public | BindingFlags.Static),
    a);
LambdaExpression lambda = Expression.Lambda(methodCall, a);
Console.WriteLine(lambda); 

但结果总是a => Sin(a)

我也试过

Expression<Func<Double, Double>> lambda = a => Math.Sin(a);

却得到相同的结果。我错过什么了吗?

如何创建这个表达式树(静态方法)

如果你真的需要改变在纯文本中表示表达式的方式,这可能会给你一个(非常非常混乱和快速的)开始:

private string MyToString(Expression e)
{
    var lam = e as LambdaExpression;
    if (lam != null)
    {
        var pStr = lam.Parameters.Select(p => MyToString(p));
        var paramStr = pStr.Any() ? string.Format("({0})", string.Join(", ", pStr)) : "()";
        var bodyExpr = MyToString(lam.Body);
        return paramStr + " => "  + bodyExpr;
    }
    var param = e as ParameterExpression;
    if (param != null)
    {
        return param.Name;
    }
    var methodExpression = e as MethodCallExpression;
    if (methodExpression != null)
    {
        string methodName;
        if (methodExpression.Method.IsStatic)
            methodName = methodExpression.Method.DeclaringType.Name + "." + methodExpression.Method.Name;
        else
            methodName = methodExpression.Method.Name;
        var pStr = methodExpression.Arguments.Select(p => MyToString(p));
        var paramStr = pStr.Any() ? string.Format("({0})", string.Join(", ", pStr)) : "()";
        return methodName + paramStr;
    }
    return e.ToString();
}

调用方式:

ParameterExpression a = Expression.Parameter(typeof(Double), "a");
MethodCallExpression methodCall = Expression.Call(
    typeof(Math).GetMethod("Sin", BindingFlags.Public | BindingFlags.Static),
    a);
LambdaExpression lambda = Expression.Lambda(methodCall, a);
MyToString(lambda).Dump();

给:

(a) => Math.Sin(a)
但是要注意,如果你真的沿着这条路走下去,你将需要覆盖所有的边缘情况,并且你最终会发现除了一个简单的表达式之外的任何事情都将变得比它值得的更多。

话虽如此,你需要决定这是否真的值得,或者你是否可以采取另一种方法。

刚刚在网上找到这个:https://github.com/JakeGinnivan/ExpressionToString/blob/master/src/ExpressionToString/ExpressionStringBuilder.cs

如果你编辑VisitMethodCall来打印静态方法调用的类名,它会给你你想要的。这种方法更接近于正常的表达式树处理实践,因为它使用了一个正常的expressionvisitor,而不是一个递归的单一方法。

这段代码不是我写的,只是发现了它,但乍一看似乎很有希望。

github中有一个名为TryRoslyn的项目,其中有一个Roslyn项目的游乐场网站。
如果需要从代码中创建表达式树,只需粘贴代码并查看表达式树的输出。
我已经举了一个Expression<Func<double, double>> b = a => Math.Sin(a);

的例子