Вычисление дерева выражений со многими параметрами - PullRequest
3 голосов
/ 13 сентября 2009

Я пытаюсь использовать дерево выражений и объекты Lamdba Expression в .Net 3.5, чтобы позволить мне динамически вычислять логическое выражение, введенное пользователем.

Пока пользователь может создать дерево выражений, состоящее из BinarayExpressions, в которых значения AND и OR выражаются как ParameterExpressions. Затем я планировал создать LambdaExpression на основе этого дерева, чтобы я мог скомпилировать выражение в делегат, который затем мог бы вызвать. У меня проблема в том, что я не знаю, сколько входных параметров понадобится пользователю, поэтому, когда я прихожу, чтобы скомпилировать выражение в делегат, я не знаю, каким должен быть метод подписи до времени выполнения. *

Пока что я нашел два возможных решения.

  1. Создайте целую группу делегатов как Func<bool, bool, bool...> те, которые могут принять столько параметров, сколько, я думаю, может понадобиться пользователю. Это не самое элегантное решение, но я думаю, что оно будет работать, пока кто-то не захочет использовать еще один параметр, чем я учел.
  2. Передайте массив значений и каким-то образом назначьте их моим параметрам, используя индексатор массива. Я думал об этом, но не могу понять, как это работает.

NB. Нужно быть быстрым, чтобы не было бокса или чего-то подобного.

1 Ответ

3 голосов
/ 13 сентября 2009

Я сделал точно это раньше, используя подход массива (для Finguistics , как это происходит). Хитрость Expression.ArrayIndex:

    var arr = Expression.Parameter(typeof(int[]), "arr");
    var body = Expression.ArrayIndex(arr, Expression.Constant(1));
    var expr = Expression.Lambda<Func<int[], int>>(body, arr);
    var func = expr.Compile();

    int[] vals = { 7, 8, 9 };
    int i = func(vals);

Преимущество подхода с использованием массива состоит в том, что вы можете сохранять строго типизированный тип делегата (Func<int[],int> или аналогичный, независимо от количества аргументов. И набранный Invoke намного быстрее, чем DynamicInvoke.

Если значения не все одного типа - это тоже выполнимо; дайте мне знать, и я добавлю пример.

...