Числовые выражения, введенные пользователем в 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 и отображает его.
