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

时间:2015-09-24 03:44:48

标签: c# .net expression-trees

我想使用以下代码为dat <- structure(list(ID = c(1, 1, 1, 1, 1), Year = c(1950, 1950, 1950, 1950, 1950), Month = c(1, 1, 1, 2, 2), Variable = c("PRCP", "TMAX", "TMIN", "PRCP", "TMAX"), Value1 = c(0, 52, 41, 1, 55), Value2 = c(1, 51, 41, 0, 57), Value3 = c(0, 52, 39, 1, 58)), .Names = c("ID", "Year", "Month", "Variable", "Value1", "Value2", "Value3"), row.names = c(NA, -5L), class = "data.frame") 创建表达式树对象:

a => Math.Sin(a)

但结果总是a =&gt;罪的(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); 

但获得相同的结果。 我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

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

lines.map ( line => line.substring(10,20) )

叫做:

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();

请注意,如果你沿着这条路走下去,你需要涵盖所有边缘情况,你最终会找到更多的东西,而不是一个简单的表达式会比它更努力价值。

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

答案 1 :(得分:1)

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

如果您编辑VisitMethodCall以打印静态方法调用的类名,它会为您提供所需的内容。这种方法更接近正常的表达式树处理实践,因为它使用普通的表达式访问器,而不是递归的单一方法。

我没有写这个代码,只是发现它,但起初看起来很有希望。

答案 2 :(得分:1)

在github中有一个名为TryRoslyn的项目,其中有一个playground站点用于Roslyn项目。
如果您需要从代码中创建表达式树,只需粘贴代码并查看表达式树的输出。
我已经Expression<Func<double, double>> b = a => Math.Sin(a); extern "C" { typedef SSL_METHOD*(*MethodFuncPtr)(void); typedef const SSL_METHOD*(*ConstMethodFuncPtr)(void); } class Method { public: Method(SSL_METHOD *method); static ConstMethodFuncPtr TLSv1; private: SSL_METHOD *m_method; };