C # скомпилировать числовое выражение - PullRequest
2 голосов
/ 19 декабря 2008

Предположим, я разрешаю пользователю вводить произвольное числовое выражение, которое позволяет использовать явный набор функций и предопределенных переменных.

Интерпретация этого довольно проста, но что, если производительность является критическим фактором?

Мне нужен способ для компиляции (во время выполнения) строки с выражением во что-то, что может быть выполнено 20K раз с разными значениями переменных.

Ответы [ 3 ]

2 голосов
/ 19 декабря 2008

Так что вы действительно хотите разобрать строку в (в конце концов) типизированном делегате.

Одна опция, затем она для разбора строки в Expression, которую вы затем можете скомпилировать в лямбду. Это довольно сложно, но у меня есть некоторый код, который сделает большую часть этого - но, возможно, существуют существующие парсеры, которые уже выполняют эту работу полностью.

В качестве тривиального Expression примера:

    var x = Expression.Parameter(typeof(double), "x");
    var y = Expression.Parameter(typeof(double), "y");
    var body = Expression.Multiply(x, y);
    var func = Expression.Lambda<Func<double, double,double>>(body, x, y).Compile();

    double z = func(123.45, 678.90);

Проблема в остальном коде синтаксического анализа; -p

На прошлой неделе я написал синтаксический анализатор string to Expression, но он содержит больше кода, чем я обычно публикую здесь ... более 300 строк (не включая распознавание сделанных на заказ внешних функций или именованных аргументов (в настоящее время использует анонимные "?" заполнители)).

но если (как вы говорите) интерпретация проста, то, возможно, использовать подобный код для написания Expression, который вы можете скомпилировать?

2 голосов
/ 19 декабря 2008

Примеры Linq от Microsoft уже содержат реализацию расширяемого синтаксического анализатора Linq.

sealed class Order
{
  public double SubTotal { get; set; }
  public double Shipping { get; set; }
}
static void Main()
{
  var calculateTotal = DynamicExpression
    .ParseLambda<Order, double>("SubTotal*@0+Shipping", 0.12)
    .Compile();

  var order = new Order
  {
    SubTotal = 124.99,
    Shipping = 7.99
  };
  Console.WriteLine(calculateTotal(order));
  Console.ReadLine();
}

Вы можете проверить проект DbLinq для источников или этот пост для более подробной информации: Динамический анализ Linq и Expression в .NET как подсказка расширяемости компилятора C #

1 голос
/ 19 декабря 2008

В C # 4.0 это станет очень просто и понятно. Однако до C # 4.0 я предлагаю вам использовать Microsoft.JScript библиотеки для этого.

Это все, что вы хотите: http://www.odetocode.com/Articles/80.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...