Составители:
Рубрика:
parameters.ReferencedAssemblies.Add(“System.dll”);
parameters.ReferencedAssemblies.Add(“Integral.exe”);
parameters.GenerateInMemory = true;
string e = expr.GenerateCS();
string code = “public class FunctionCS: Function\n”+
“{\n”+
“ public override double Eval(double x)\n”+
“ {\n”+
“ return “+e+”;\n”+
“ }\n”+
“}\n”;
CompilerResults compilerResults =
compiler.CompileAssemblyFromSource(parameters,code);
Assembly assembly = compilerResults.CompiledAssembly;
return assembly.CreateInstance(“FunctionCS”) as Function;
}
Классы, отвечающие за компиляцию исходного кода, относятся к
пространству имен System.CodeDom.Compiler.
Основную функциональность, необходимую нам для компиляции
сгенерированной C#-программы, обеспечивает класс CSharpCodeProvider.
Метод CreateCompiler этого класса создает экземпляр компилятора C#, к
которому можно обращаться через интерфейс ICodeCompiler.
Параметры компиляции задаются через объект класса
CompilerParameters. В нашем случае это имена сборок, импортируемых ге-
нерируемой программой: System.dll и Integral.exe. Обратите внимание,
что Integral.exe – это сборка, получаемая при компиляции рассматрива-
емого нами примера. Она импортируется по причине того, что динамиче-
ски генерируемый класс FunctionCS должен наследовать от определенного
в ней абстрактного класса Function.
Параметры компиляции и строка, содержащая текст программы, пе-
редаются методу CompileAssemblyFromSource экземпляра компилятора C#.
Метод компилирует программу и возвращает объект класса
CompilerResults, содержащий результаты компиляции. Из этого объекта
мы можем получить объект рефлексии Assembly, представляющий создан-
ную в памяти динамическую сборку. Используя данный объект, мы созда-
ем экземпляр определенного в динамической сборке класса FunctionCS,
который в дальнейшем может быть использован для вычисления значения
функции в процессе интегрирования.
Динамическая генерация кода
167
непосредственное вычисление значения выражения, метод GenerateCS
транслирует выражение в фрагмент программы на C#, а метод GenerateCIL
транслирует выражение в CIL-код.
Вопросы генерации кода будут обсуждаться в следующих разделах,
поэтому сейчас мы только приведем пример CIL-кода, генерируемого ме-
тодом GenerateCIL для дерева объектов, которые представляют выражение
”2*x*x*x+3*x*x+4*x+5”:
ldc.r8 2.0
ldarg.1
mul
ldarg.1
mul
ldarg.1
mul
ldc.r8 3.0
ldarg.1
mul
ldarg.1
mul
add
ldc.r8 4.0
ldarg.1
mul
add
ldc.r8 5.0
add
Метод GenerateCS фактически восстанавливает из дерева строковое
представление выражения и в особых комментариях не нуждается.
5.1.3. Трансляция выражений в C#
Как уже говорилось, самым простым способом динамической гене-
рации кода является порождение текста C#-программы и компиляция
этой программы с помощью компилятора C#, доступного через библиоте-
ку классов .NET.
В нашем примере динамическую генерацию сборки осуществляет
статический метод CompileToCS, который получает транслируемое выраже-
ние в виде объекта класса Expression и возвращает объект Function:
static Function CompileToCS(Expression expr)
{
ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();
CompilerParameters parameters = new CompilerParameters();
166
CIL и системное программирование в Microsoft .NET
166 CIL и системное программирование в Microsoft .NET Динамическая генерация кода 167 непосредственное вычисление значения выражения, метод GenerateCS parameters.ReferencedAssemblies.Add(“System.dll”); транслирует выражение в фрагмент программы на C#, а метод GenerateCIL parameters.ReferencedAssemblies.Add(“Integral.exe”); транслирует выражение в CIL-код. parameters.GenerateInMemory = true; Вопросы генерации кода будут обсуждаться в следующих разделах, поэтому сейчас мы только приведем пример CIL-кода, генерируемого ме- string e = expr.GenerateCS(); тодом GenerateCIL для дерева объектов, которые представляют выражение string code = “public class FunctionCS: Function\n”+ ”2*x*x*x+3*x*x+4*x+5”: “{\n”+ ldc.r8 2.0 “ public override double Eval(double x)\n”+ ldarg.1 “ {\n”+ mul “ return “+e+”;\n”+ ldarg.1 “ }\n”+ mul “}\n”; ldarg.1 mul CompilerResults compilerResults = ldc.r8 3.0 compiler.CompileAssemblyFromSource(parameters,code); ldarg.1 Assembly assembly = compilerResults.CompiledAssembly; mul return assembly.CreateInstance(“FunctionCS”) as Function; ldarg.1 } mul Классы, отвечающие за компиляцию исходного кода, относятся к add пространству имен System.CodeDom.Compiler. ldc.r8 4.0 Основную функциональность, необходимую нам для компиляции ldarg.1 сгенерированной C#-программы, обеспечивает класс CSharpCodeProvider. mul Метод CreateCompiler этого класса создает экземпляр компилятора C#, к add которому можно обращаться через интерфейс ICodeCompiler. ldc.r8 5.0 Параметры компиляции задаются через объект класса add CompilerParameters. В нашем случае это имена сборок, импортируемых ге- Метод GenerateCS фактически восстанавливает из дерева строковое нерируемой программой: System.dll и Integral.exe. Обратите внимание, представление выражения и в особых комментариях не нуждается. что Integral.exe – это сборка, получаемая при компиляции рассматрива- емого нами примера. Она импортируется по причине того, что динамиче- 5.1.3. Трансляция выражений в C# ски генерируемый класс FunctionCS должен наследовать от определенного Как уже говорилось, самым простым способом динамической гене- в ней абстрактного класса Function. рации кода является порождение текста C#-программы и компиляция Параметры компиляции и строка, содержащая текст программы, пе- этой программы с помощью компилятора C#, доступного через библиоте- редаются методу CompileAssemblyFromSource экземпляра компилятора C#. ку классов .NET. Метод компилирует программу и возвращает объект класса В нашем примере динамическую генерацию сборки осуществляет CompilerResults, содержащий результаты компиляции. Из этого объекта статический метод CompileToCS, который получает транслируемое выраже- мы можем получить объект рефлексии Assembly, представляющий создан- ние в виде объекта класса Expression и возвращает объект Function: ную в памяти динамическую сборку. Используя данный объект, мы созда- static Function CompileToCS(Expression expr) ем экземпляр определенного в динамической сборке класса FunctionCS, { который в дальнейшем может быть использован для вычисления значения ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler(); функции в процессе интегрирования. CompilerParameters parameters = new CompilerParameters();
Страницы
- « первая
- ‹ предыдущая
- …
- 88
- 89
- 90
- 91
- 92
- …
- следующая ›
- последняя »