C# String.IndexOf方法的表达式树

C# String.IndexOf方法的表达式树,c#,reflection,expression-trees,linq-expressions,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 Ex

我应该如何为
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
参数,我可以让它工作


谢谢

我想有两个问题

第一个是获取方法的方式-您要求的方法只有一个字符串参数,而不是一个有两个参数:

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"));
    }
}
使用系统;
使用System.Linq.Expressions;
课堂测试
{
静态void Main()
{
var method=typeof(string).GetMethod(“IndexOf”,
新[]{typeof(string),typeof(StringComparison)};
var left=表达式参数(typeof(string),“left”);
var right=Expression.Parameter(typeof(string),“right”);
表达式[]parms=新表达式[]{right,
常量表达式(StringComparison.OrdinalIgnoreCase)};
var call=Expression.call(左,方法,参数);
var lambda=表达式.lambda
(呼叫,左,右);
var compiled=lambda.Compile();
Console.WriteLine(compiled.Invoke(“hello THERE”,“lot”));
}
}

我没有检查它的其余部分,但如果只有枚举造成问题:

Expression.Constant(StringComparison.OrdinalIgnoreCase)

你有更多的选择。或者检查我的答案


编辑:忘记妄想症。

最简单的方法是通过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"));
//编译器将lambda转换为表达式
表达式=(s1,s2)=>s1.IndexOf(s2,StringComparison.OrdinalIgnoreCase);
//编译表达式以便调用它
var func=expression.Compile();
//产出2
Console.WriteLine(func(“区分大小写”、“区分se”);
这比手动构建表达式树更具可读性和可维护性


我经常对大量的人直接投入到手动构建表达式树中感到惊讶。当你可以让编译器为你做这项工作时,你没有必要去问问题。

就像以往一样,当你遇到问题时,你应该说你尝试的东西出了什么问题-你是否遇到了异常、编译时错误,仅仅是错误的行为?如果是某种错误,那是什么错误?对不起。下次提问时我会记住这一点。我遇到了ArgumentException。应该有帮助:+1,当编译器可以手动构建表达式树时,没有理由手动构建表达式树you@Thomas:是的,但我们看不到
从这里来。。。它们可能是
Expression
,而不是
string
。也许这是更好的方法,但我正在处理的库()是通过手动构建表达式树来构建的。现在我只需要添加一个字符串比较方法调用,但可能需要使用lambdas重构/重写所有内容。有没有办法对
包含的
方法执行相同的操作?@atp9:Yes。你试过什么,出了什么问题?我试过这样的方法:
MethodInfo method=typeof(string).GetMethod(“Contains”,new[]{typeof(string),typeof(StringComparison)});var expressionbody=System.Linq.Expressions.Expression.Call(prop,method,new[]{valuetocompare,System.Linq.Expressions.Expression.Constant(StringComparison.OrdinalIgnoreCase)})但是这个给了我一个error@atp9:考虑到注释对扩展代码不是很好,我建议你用一个新的注释来问一个新问题。
//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"));