C# - я могу определить функцию на лету из предоставленной пользователем формулы строки?

Я могу определить функцию с лямбда-выражением, как в:

Func <int, int, int> Fxy = ( (a,b) => a + b ) );  // Fxy does addition

Но что, если я хотел бы разрешить пользователю указывать правую часть лямбда-выражения во время выполнения?

String formula_rhs = Console.Readline();
// user enters "a - b"

Могу ли я как-то изменить Fxy, как если бы я закодировал

Func <int, int, int> Fxy = ( (a,b) => a - b ) );  // Fxy does what the user wants 
                                                  // (subtraction)

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

5 ответов

Попробуйте структуру ncalc: http://ncalc.codeplex.com/ Это просто и легко.

Пространство имен System.Reflection.Emit предназначено для генерации кода на лету. Это довольно сложно в целом, но может помочь для простых функций, таких как вычитание.

Это не так просто. Эта библиотека содержит некоторые функции Dynamic Linq, которые вы можете использовать для преобразования лямбда-выражения из текста в Func<>, посмотрите на это.

Если вы планируете использовать несложные формулы, механизм JScript будет простым решением:

        Microsoft.JScript.Vsa.VsaEngine engine = Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
        MessageBox.Show(Microsoft.JScript.Eval.JScriptEvaluate("((2+3)*5)/2", engine).ToString());

Не забудьте добавить ссылку на Microsoft.JScript сборка

Использование Linq.Expressions может быть идеей здесь.

Ваш пример будет переведен на:

var a = Expression.Parameter(typeof(int), "a");
var b = Expression.Parameter(typeof(int), "b");
var sum = Expression.Subtract(a, b);
var lamb = Expression.Lambda<Func<int, int, int>>(sum, a, b);
Func<int, int, int> Fxy = lamb.Compile();

Конечно, вы получите удовольствие от анализа строки в правильных выражениях.:-)

Другие вопросы по тегам