String.IndexOf方法的表达式树

时间:2011-08-17 07:27:08

标签: c# reflection expression-trees linq-expressions

我应该如何构建string.IndexOf("substring", StringComparison.OrdinalIgnoreCase)的表达式树?

我可以在没有第二个参数的情况下使其工作:StringComparison.OrdinalIgnoreCase。这些是我到目前为止的尝试:

var methodCall = typeof (string).GetMethod("IndexOf", new[] {typeof (string)});
Expression[] parms = new Expression[]{right, Expression.Constant("StringComparison.OrdinalIgnoreCase", typeof (Enum))};
var exp =  Expression.Call(left, methodCall, parms);
return exp;

还试过这个:

var methodCall = typeof (string).GetMethod(method, new[] {typeof (string)});
Expression[] parms = new Expression[]{right, Expression.Parameter(typeof(Enum) , "StringComparison.OrdinalIgnoreCase")};
var exp =  Expression.Call(left, methodCall, parms);
return exp;

请记住,如果忽略OrdinalIgnoreCase参数,我可以使其正常工作。

由于

3 个答案:

答案 0 :(得分:12)

我怀疑有两个问题。

首先是你获得方法的方式 - 你要求只有一个字符串参数的方法,而不是一个有两个参数的方法:

var methodCall = typeof (string).GetMethod("IndexOf",
                            new[] { typeof (string), typeof(StringComparison) });

第二个是你给出的 - 它应该是常量的实际值,而不是字符串:

Expression[] parms = new Expression[] { right, 
    Expression.Constant(StringComparison.OrdinalIgnoreCase) };

编辑:这是一个完整的工作样本:

using System;
using System.Linq.Expressions;

class Test
{
    static void Main()
    {
        var method = typeof (string).GetMethod("IndexOf",
                new[] { typeof (string), typeof(StringComparison) });

        var left = Expression.Parameter(typeof(string), "left");
        var right = Expression.Parameter(typeof(string), "right");

        Expression[] parms = new Expression[] { right, 
                Expression.Constant(StringComparison.OrdinalIgnoreCase) };

        var call = Expression.Call(left, method, parms);
        var lambda = Expression.Lambda<Func<string, string, int>>
            (call, left, right);

        var compiled = lambda.Compile();
        Console.WriteLine(compiled.Invoke("hello THERE", "lo t"));
    }
}

答案 1 :(得分:3)

最简单的方法是通过这样的lambda来获取它:

//the compiler will convert the lambda into an expression
Expression<Func<string, string, int>> expression = (s1, s2) => s1.IndexOf(s2, StringComparison.OrdinalIgnoreCase);
//compile the expression so we can call it
var func = expression.Compile();
//outputs 2
Console.WriteLine(func("Case Sensitive", "se sensitive"));

这比手动构建表达式树更具可读性和可维护性。

我一直对直接进入手动构建表达树的人数感到惊讶。没有必要在什么时候让编译器为你完成工作。

答案 2 :(得分:0)

我没有检查其余部分,但是如果只有枚举产生问题:

Expression.Constant(StringComparison.OrdinalIgnoreCase)

Expression.Constant(Enum.Parse(typeof(StringComparison), "OrdinalIgnoreCase"), typeof(Enum));

你有更多的选择。或者查看我的回答here

编辑:忘记了paranthesis。