Числовые выражения, введенные пользователем в C#
В этом примере показан один способ оценки математических выражений, введенных пользователем во время выполнения.
Введите числовое выражение, включающее x и y в верхнем текстовом поле. Затем введите значения для x и y в нижних текстовых полях и нажмите кнопку «Оценить», чтобы программа оценивала выражение.
Программа выполняет следующий код, когда вы нажимаете кнопку «Оценить».
// Оценим выражение. private void btnEvaluate_Click(object sender, EventArgs e) { // Поверните уравнение в функцию. string function_text = "public static class Evaluator" + "{" + " public static double Evaluate(double x, double y)" + " {" + " return " + txtExpression.Text + ";" + " }" + "}"; // Компилируем функцию. CodeDomProvider code_provider = CodeDomProvider.CreateProvider("C#"); // Создаем неиспользуемую сборку в памяти. CompilerParameters parameters = new CompilerParameters(); parameters.GenerateInMemory = true; parameters.GenerateExecutable = false; // Компилируем код. CompilerResults results = code_provider.CompileAssemblyFromSource(parameters, function_text); // Если есть ошибки, отобразите их. if (results.Errors.Count > 0) { string msg = "Error compiling the expression."; foreach (CompilerError compiler_error in results.Errors) { msg += "\n" + compiler_error.ErrorText; } MessageBox.Show(msg, "Expression Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // Получить тип класса Evaluator. Type evaluator_type = results.CompiledAssembly.GetType("Evaluator"); // Получить объект MethodInfo, описывающий метод Evaluate. MethodInfo method_info = evaluator_type.GetMethod("Evaluate"); // Создаем список параметров. object[] method_params = new object[] { double.Parse(txtX.Text), double.Parse(txtY.Text) }; // Выполнить метод. double expression_result = (double)method_info.Invoke(null, method_params); // Отобразим возвращенный результат. txtResult.Text = expression_result.ToString(); } }
Сначала код состоит из класса, который включает в себя одну функцию, содержащую выражение, введенное пользователем. Результат выглядит примерно так:
public static class Evaluator { public static double Evaluate(double x, double y) { return 2 * x + 4 * y + x * y; } }
Фактическая строка имеет класс и его функцию на одной строке текста. Я добавил здесь разрывы строк, чтобы сделать его более читаемым, но компилятору все равно.
Далее код создает CodeDomProvider для компиляции кода C#. Он использует параметры, чтобы сообщить провайдеру создать неиспользуемую сборку, построенную в памяти, а затем вызывает метод CompileAssemblyFromSource для компиляции класса Evaluator с его Evaluate.
Если есть ошибки, программа отображает их. Попробуйте добавить некоторые синтаксические ошибки в уравнение, чтобы увидеть, что происходит. Если ошибка не слишком экстремальна, сообщения об ошибках часто достаточно хороши, чтобы вы могли исправить эту проблему.
Затем код получает Type, представляющий класс Evaluator, и из него получает объект MethodInfo, представляющий класс Evaluate tt>. Программа создает массив параметров, который содержит значения x и y для перехода в метод и вызывает метод, передавая ему эти параметры. Программа преобразует результат возврата метода из общего объекта в double и отображает его.