我有一个相当简单的表达式解析器,它使用Linq.Expression命名空间。
输入类似于:(1 + 1),它找到左和右常量,并将operator char转换为ExpressionTypes枚举值,创建适当的表达式,编译并执行。
我真的希望能够进行字符串操作,(abc
+ def
)会评估为abcdef
,但是:
System.InvalidOperationException:没有为类型'System.String'和'System.String'定义二进制运算符Add
我将如何自己实施?
类似于ExpressionTypes.Concat的方法是理想的。
答案 0 :(得分:2)
您必须自己创建MethodCallExpression,在本例中是针对静态方法string.Concat。 (这是编译器在编译此类代码时自行执行的操作)
答案 1 :(得分:1)
这里有一些代码演示了如何使用MethodInfo扩展二进制表达式的定义Add to串联字符串。
一个示例使用String类型中的现有Concat方法。
第二个示例在Program类型中使用自定义Concat方法(该类全部嵌入在其中):
private MethodInfo ConcatMethod = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
private MethodInfo ConcatMethod2 = typeof(Program).GetMethod("Concat", new Type[] { typeof(string), typeof(int) });
public static string Concat(string obj1, int obj2)
{
return string.Concat(obj1, obj2.ToString());
}
private Expression SomeCode(string leftStr, string rightStr)
{
Expression left = Expression.Constant(leftStr);
Expression right = Expression.Constant(rightStr);
return Expression.Add(left, right, ConcatMethod);
}
private Expression SomeCode(string leftStr, int rightInt)
{
Expression left = Expression.Constant(leftStr);
Expression right = Expression.Constant(rightInt);
return Expression.Add(left, right, ConcatMethod2);
}
static void CheesyTest2()
{
Program foo = new Program();
Expression exp = foo.SomeCode("abc", "def");
LambdaExpression lambdaExpression = Expression.Lambda(exp);
Delegate func = lambdaExpression.Compile();
object result = func.DynamicInvoke();
Console.WriteLine(string.Format("Expression result: {0}", result));
exp = foo.SomeCode("abc", 42);
lambdaExpression = Expression.Lambda(exp);
func = lambdaExpression.Compile();
result = func.DynamicInvoke();
Console.WriteLine(string.Format("Expression2 result: {0}", result));
}
答案 2 :(得分:0)
对于自定义运算符,它实际上是一个方法调用,因此您需要找到相应的方法并创建用于调用该方法的表达式树。没有与表达树一起工作太多,所以我很害怕我不能给你一个代码样本,但我希望这有帮助