Создание исходного кода и компиляция программы из графа CodeDOM
Обновлен: Ноябрь 2007
Пространство имен System.CodeDom.Compiler предоставляет интерфейсы для создания исходного кода из графов объекта CodeDOM и для управления компиляцией в поддерживаемых компиляторах. Поставщик кода может создавать исходный код на конкретном языке программирования, используя граф CodeDOM. Класс, который является производным из CodeDomProvider, как правило, может предоставлять методы для создания и компиляции кода для языка, поддерживаемого поставщиком.
Использование поставщика кода CodeDOM для создания исходного кода
Чтобы создать исходный код на конкретном языке, необходим граф CodeDOM, представляющий структуру создаваемого исходного кода.
В следующем примере демонстрируется создание экземпляра CSharpCodeProvider.
Dim provider As New CSharpCodeProvider()
CSharpCodeProvider provider = new CSharpCodeProvider();
Граф для создания кода, как правило, содержится в CodeCompileUnit. Чтобы создать код для CodeCompileUnit, содержащего граф CodeDOM, вызовите метод GenerateCodeFromCompileUnit поставщика кода. Этот метод имеет параметр для указания объекта TextWriter, используемого для создания кода, поэтому иногда сначала необходимо создавать TextWriter, который и будет осуществлять запись. В следующем примере демонстрируется генерация кода из CodeCompileUnit и запись созданного исходного кода в файл с именем HelloWorld.cs.
Public Shared Function GenerateCSharpCode( _
compileunit As CodeCompileUnit) As String
' Generate the code with the C# code provider.
Dim provider As CSharpCodeProvider = New CSharpCodeProvider()
' Build the output file name.
Dim sourceFile As String
If provider.FileExtension.StartsWith(".")
sourceFile = "HelloWorld" + provider.FileExtension
Else
sourceFile = "HelloWorld." + provider.FileExtension
End If
' Create a TextWriter to a StreamWriter to an output file.
Dim tw As New IndentedTextWriter( _
New StreamWriter(sourceFile, False), " ")
' Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit(compileunit, tw, _
New CodeGeneratorOptions())
' Close the output file.
tw.Close()
Return sourceFile
End Function
public static String GenerateCSharpCode(CodeCompileUnit compileunit)
{
// Generate the code with the C# code provider.
CSharpCodeProvider provider = new CSharpCodeProvider();
// Build the output file name.
String sourceFile;
if (provider.FileExtension[0] == '.')
{
sourceFile = "HelloWorld" + provider.FileExtension;
}
else
{
sourceFile = "HelloWorld." + provider.FileExtension;
}
// Create a TextWriter to a StreamWriter to the output file.
IndentedTextWriter tw = new IndentedTextWriter(
new StreamWriter(sourceFile, false), " ");
// Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit(compileunit, tw,
new CodeGeneratorOptions());
// Close the output file.
tw.Close();
return sourceFile;
}
Использование поставщика кода CodeDOM для компиляции сборок
Вызов процесса компиляции
Чтобы скомпилировать сборку, используя поставщик CodeDom, необходимо иметь либо исходный код для компиляции на языке, для которого есть компилятор, либо граф CodeDOM, из которого может быть создан исходный код для компиляции.
При компиляции из графа CodeDOM передайте объект CodeCompileUnit, содержащий граф, в метод CompileAssemblyFromDom поставщика кода. Если имеется файл исходного кода на языке, воспринимаемом компилятором, передайте имя файла, содержащего исходный код, в метод CompileAssemblyFromFile поставщика CodeDom. Также можно передать строку, содержащую исходный код на языке, воспринимаемом компилятором, в метод CompileAssemblyFromSource поставщика CodeDom.
Настройка параметров компиляции
Все стандартные методы вызова компиляции поставщика CodeDom имеют параметр типа CompilerParameters, который указывает параметры, используемые при компиляции.
Можно указать имя файла для выходной сборки в свойстве OutputAssembly объекта CompilerParameters. Иначе будет использовано имя выходного файла по умолчанию.
По умолчанию инициализируется новый объект CompilerParameters со свойством GenerateExecutable, равным false. При компиляции исполняемой программы необходимо установить значение свойства GenerateExecutable равным true. Если значение GenerateExecutable равно false, то компилятор создает библиотеку классов.
При компиляции исполняемой программы из графа CodeDOM следует определить в графе объект CodeEntryPointMethod. Если в коде имеется несколько точек входа, может понадобиться задать свойство MainClass объекта CompilerParameters равным имени класса, в котором определяется используемая точка входа.
Чтобы включить сведения об отладке в создаваемый исполняемый файл, присвойте свойству IncludeDebugInformation значение true.
Если проект ссылается на какие-либо сборки, необходимо указать имена этих сборок, как элементы в коллекции StringCollection, так же, как свойство ReferencedAssemblies объекта CompilerParameters используется при вызове компиляции.
Для того чтобы скомпилированная сборка записывалась в память, а не на диск, задайте для свойства GenerateInMemory значение true. При создании сборки в памяти код может получить ссылку на создаваемую сборку из свойства CompiledAssembly объекта CompilerResults. При записи сборки на диск можно получить путь к созданной сборке из свойства PathToAssembly , объекта CompilerResults.
Чтобы указать пользовательскую строку аргументов командной строки, которую следует использовать при вызове процесса компиляции, задайте строку в свойстве CompilerOptions.
Если для вызова процесса компилятора требуется маркер безопасности Win32, задайте этот маркер в свойстве UserToken.
Чтобы сделать ссылку на исходный файл Win32 в скомпилированной сборке, укажите имя исходного файла Win32 в свойстве Win32Resource.
Чтобы указать уровень предупреждения, на котором следует прекратить компиляцию, задайте свойство WarningLevel как целое число, представляющее уровень предупреждения для прекращения компиляции. Также можно настроить компилятор на прекращение компиляции при обнаружении предупреждений, задав для свойства TreatWarningsAsErrors значение true.
В следующем примере кода показана компиляция исходного файла с помощью поставщика CodeDom, производного из класса CodeDomProvider.
Public Shared Function CompileCSharpCode(sourceFile As String, _
exeFile As String) As Boolean
Dim provider As CSharpCodeProvider = New CSharpCodeProvider()
' Build the parameters for source compilation.
Dim cp As New CompilerParameters()
' Add an assembly reference.
cp.ReferencedAssemblies.Add("System.dll")
' Save the assembly as a physical file.
cp.GenerateInMemory = False
' Generate an executable instead of a class library.
cp.GenerateExecutable = True
' Set the assembly file name to generate.
cp.OutputAssembly = exeFile
' Invoke compilation.
Dim cr As CompilerResults = _
provider.CompileAssemblyFromFile(cp, sourceFile)
If cr.Errors.Count > 0 Then
' Display compilation errors.
Console.WriteLine("Errors building {0} into {1}", _
sourceFile, cr.PathToAssembly)
Dim ce As System.CodeDom.Compiler.CompilerError
For Each ce In cr.Errors
Console.WriteLine(" {0}", ce.ToString())
Console.WriteLine()
Next ce
Else
Console.WriteLine("Source {0} built into {1} successfully.", _
sourceFile, cr.PathToAssembly)
End If
' Return the results of compilation.
If cr.Errors.Count > 0 Then
Return False
Else
Return True
End If
End Function
public static bool CompileCSharpCode(String sourceFile,
String exeFile)
{
CSharpCodeProvider provider = new CSharpCodeProvider();
// Build the parameters for source compilation.
CompilerParameters cp = new CompilerParameters();
// Add an assembly reference.
cp.ReferencedAssemblies.Add( "System.dll" );
// Generate an executable instead of
// a class library.
cp.GenerateExecutable = true;
// Set the assembly file name to generate.
cp.OutputAssembly = exeFile;
// Save the assembly as a physical file.
cp.GenerateInMemory = false;
// Invoke compilation.
CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
if(cr.Errors.Count > 0)
{
// Display compilation errors.
Console.WriteLine("Errors building {0} into {1}",
sourceFile, cr.PathToAssembly);
foreach(CompilerError ce in cr.Errors)
{
Console.WriteLine(" {0}", ce.ToString());
Console.WriteLine();
}
}
else
{
Console.WriteLine("Source {0} built into {1} successfully.",
sourceFile, cr.PathToAssembly);
}
// Return the results of compilation.
if (cr.Errors.Count > 0)
{
return false;
}
else
{
return true;
}
}
Встроенная поддержка языков
.NET Framework предоставляет компиляторы и генераторы кода для следующих языков: C#, Visual Basic, C++, J# и JScript. Поддержка CodeDOM может быть расширена на другие языки путем реализации генераторов и компиляторов кода для определенных языков.