Дерево выражений для метода String.IndexOf - PullRequest
8 голосов
/ 17 августа 2011

Как мне построить дерево выражений для 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 ]

12 голосов
/ 17 августа 2011

Я подозреваю, что есть две проблемы.

Во-первых, вы получаете метод - вы запрашиваете метод только с одним строковым параметром вместоодин с двумя параметрами:

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"));
    }
}
3 голосов
/ 17 августа 2011

Самый простой способ сделать это - получить его через лямбду:Я постоянно удивляюсь количеству людей, которые погружаются прямо в создание деревьев выражения вручную.Нет необходимости, когда вы можете заставить компилятор сделать всю работу за вас.

0 голосов
/ 17 августа 2011

Остальное я не проверял, но если только перечисление создает проблемы:

Expression.Constant(StringComparison.OrdinalIgnoreCase)

или

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

И у вас есть больше вариантов. Или проверьте мой ответ здесь .

Редактировать: забыл парантез.

...