如何创建这个表达式树(静态方法)?
How to create this expression tree (Static method)?
我想用下面的代码为 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)
不过请注意,如果您做沿着这条路走下去,您将需要涵盖所有边缘情况,并且您最终会发现除了一个简单的表达式之外的任何东西变得比它的价值更多的努力。
话虽如此,您需要决定这是否真的值得,或者您是否可以采取其他方法。
如果您编辑 VisitMethodCall 以打印静态方法调用的 class 名称,它会满足您的需求。这种方法更接近正常的表达式树处理实践,因为它使用正常的表达式访问器,而不是递归的单一方法。
这段代码不是我写的,只是找到了,但乍一看似乎很有希望。
Roslyn 项目有一个名为 TryRoslyn in github which has a playground 站点的项目。
如果您需要从您的代码创建表达式树,您只需粘贴您的代码并查看表达式树的输出。
我已经制作了 example 的 Expression<Func<double, double>> b = a => Math.Sin(a);
我想用下面的代码为 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)
不过请注意,如果您做沿着这条路走下去,您将需要涵盖所有边缘情况,并且您最终会发现除了一个简单的表达式之外的任何东西变得比它的价值更多的努力。
话虽如此,您需要决定这是否真的值得,或者您是否可以采取其他方法。
如果您编辑 VisitMethodCall 以打印静态方法调用的 class 名称,它会满足您的需求。这种方法更接近正常的表达式树处理实践,因为它使用正常的表达式访问器,而不是递归的单一方法。
这段代码不是我写的,只是找到了,但乍一看似乎很有希望。
Roslyn 项目有一个名为 TryRoslyn in github which has a playground 站点的项目。
如果您需要从您的代码创建表达式树,您只需粘贴您的代码并查看表达式树的输出。
我已经制作了 example 的 Expression<Func<double, double>> b = a => Math.Sin(a);