我正在学习有关表达式
和它们的表达式树,以便将它们与IronPython一起使用(但现在这并不重要)。
我想做的是创建一个类似于以下lambda表达式的表达式树:
Func<T, int, string> func = (s,t) => s + t;
我的当前函数是这样的:
public static Expression<Func<T, int, string>> StringConcatSelector<T>()
{
var parameterParam = Expression.Parameter(typeof(T), "x");
var paramToString = typeof(T).GetMethods().FirstOrDefault(s=>s.Name=="ToString");
var parameter = Expression.Call(parameterParam, paramToString);
var intParameterParam = Expression.Parameter(typeof(int), "s");
var intParameterToString = typeof(int).GetMethods().FirstOrDefault(s => s.Name == "ToString");
var intParameter = Expression.Call(intParameterParam, intParameterToString);
var stringConcat = typeof(string).GetMethods().FirstOrDefault(s => s.Name == "Concat");
var result = Expression.Call(stringConcat, parameter, intParameter);
return Expression.Lambda<Func<T, int, string>>
(result, parameterParam, intParameterParam);
}
Expression.Call
调用String.Concat
的方式行不通,因为参数数量无效。
所以我认为需要以下步骤:
- 创建一个
List<string>
类型的变量表达式。 - 将两个值添加到列表中。
- 使用列表表达式作为
String.Concat
的参数。
如果我是对的,那么如何创建一个List变量(或数组),并将两个值添加到其中,以便将其作为我的String.Concat
的参数?
new [] {typeof(object), typeof(object)}
来调用接受两个object
参数的重载方法,并且省去调用ToString()
的必要。对于解释表达式编译器来说,这样做可能更高效,因为解释器的步骤较少。对于IL编译器来说,可能会略显低效(直接调用int.ToString()
时不需要装箱,但是这种方式会进行装箱),但简化表达式的好处可能依然值得。 - Jon HannaExpression.Convert(expr, typeof(object))
将参数包装起来。 - Ivan StoevExpression.Call(expr, "ToString", Type.EmptyTypes)
来简化ToString
调用。 - Ivan Stoev