Создание и компиляция исходного кода из фрефа CodeDOM

Пространство имен System.CodeDom.Compiler предоставляет интерфейсы для создания исходного кода из графов объекта CodeDOM и для управления компиляцией в поддерживаемых компиляторах. Поставщик кода может создавать исходный код на конкретном языке программирования, используя граф CodeDOM. Класс, производный от CodeDomProvider, обычно может предоставлять методы для создания и компиляции кода для языка, поддерживаемого поставщиком.

Использование поставщика кода CodeDOM для создания исходного кода

Чтобы создать исходный код на конкретном языке, необходим граф CodeDOM, представляющий структуру создаваемого исходного кода.

В следующем примере демонстрируется создание экземпляра CSharpCodeProvider.

CSharpCodeProvider^ provider = gcnew CSharpCodeProvider();
CSharpCodeProvider provider = new CSharpCodeProvider();
Dim provider As New CSharpCodeProvider()

Граф для создания кода, как правило, содержится в CodeCompileUnit. Чтобы создать код для CodeCompileUnit графа CodeDOM, вызовите GenerateCodeFromCompileUnit метод поставщика кода. Этот метод имеет параметр, который используется для TextWriter создания исходного кода, поэтому иногда необходимо сначала создать объект TextWriter , в который можно записать. В следующем примере показано создание кода из CodeCompileUnit созданного исходного кода и запись в файл с именем HelloWorld.cs.

public:
    static String^ GenerateCSharpCode(CodeCompileUnit^ compileunit)
    {
        // Generate the code with the C# code provider.
        CSharpCodeProvider^ provider = gcnew 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.
        StreamWriter^ sw = gcnew StreamWriter(sourceFile, false);
        IndentedTextWriter^ tw = gcnew IndentedTextWriter(sw, "    ");

            // Generate source code using namespace the code provider.
        provider->GenerateCodeFromCompileUnit(compileunit, tw,
            gcnew CodeGeneratorOptions());

        // Close the output file.
        tw->Close();
        sw->Close();

        return sourceFile;
    }
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.
    using (StreamWriter sw = new StreamWriter(sourceFile, false))
    {
        IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");

        // Generate source code using the code provider.
        provider.GenerateCodeFromCompileUnit(compileunit, tw,
            new CodeGeneratorOptions());

        // Close the output file.
        tw.Close();
    }

    return sourceFile;
}
Public Shared Function GenerateCSharpCode(compileunit As CodeCompileUnit) As String
    ' Generate the code with the C# code provider.
    Dim provider As New CSharpCodeProvider()

    ' Build the output file name.
    Dim sourceFile As String
    If provider.FileExtension(0) = "." Then
        sourceFile = "HelloWorld" + provider.FileExtension
    Else
        sourceFile = "HelloWorld." + provider.FileExtension
    End If

    ' Create a TextWriter to a StreamWriter to the output file.
    Using sw As New StreamWriter(sourceFile, false)
        Dim tw As New IndentedTextWriter(sw, "    ")

        ' Generate source code Imports the code provider.
        provider.GenerateCodeFromCompileUnit(compileunit, tw, _
            New CodeGeneratorOptions())

        ' Close the output file.
        tw.Close()
    End Using

    Return sourceFile
End Function

Использование поставщика кода CodeDOM для компиляции сборок

Вызов компиляции

Чтобы скомпилировать сборку, используя поставщик CodeDom, необходимо иметь либо исходный код для компиляции на языке, для которого есть компилятор, либо граф CodeDOM, из которого может быть создан исходный код для компиляции.

При компиляции из графа CodeDOM передайте объект CodeCompileUnit, содержащий граф, в метод CompileAssemblyFromDom поставщика кода. Если имеется файл исходного кода на языке, который понимает компилятор, передайте имя файла, содержащего исходный код, в метод CompileAssemblyFromFile поставщика CodeDom. Также можно передать строку, содержащую исходный код на языке, воспринимаемом компилятором, в метод CompileAssemblyFromSource поставщика CodeDom.

Настройка параметров компиляции

Все стандартные методы вызова компиляции поставщика CodeDom имеют параметр типа CompilerParameters, который указывает параметры, используемые для компиляции.

Имя файла для выходной сборки можно указать в свойстве OutputAssembly объекта CompilerParameters. В противном случае будет использоваться имя выходного файла по умолчанию.

По умолчанию новый CompilerParameters инициализируется с заданным свойством GenerateExecutablefalse. Если выполняется компиляция исполняемой программы, необходимо задать GenerateExecutable для trueсвойства значение . GenerateExecutable Если задано значениеfalse, компилятор создаст библиотеку классов.

При компиляции исполняемой программы из графа CodeDOM следует определить в графе объект CodeEntryPointMethod. При наличии нескольких точек входа кода может потребоваться задать MainClass свойство CompilerParameters класса, определяющего используемую точку входа.

Чтобы включить сведения отладки в созданный исполняемый файл, задайте IncludeDebugInformation для свойства значение true.

Если проект ссылается на любые сборки, необходимо указать имена сборок в качестве элементов в StringCollection качестве ReferencedAssemblies свойства, используемого CompilerParameters при вызове компиляции.

Сборку, записанную в память, а не диск, можно скомпилировать, задав GenerateInMemory для свойства значение true. При создании сборки в памяти код может получить ссылку на создаваемую сборку из свойства CompiledAssembly объекта CompilerResults. Если сборка записывается на диск, можно получить путь к созданной сборке из PathToAssembly свойства a CompilerResults.

Чтобы указать пользовательскую строку аргументов командной строки, которую следует использовать при вызове процесса компиляции, задайте строку в свойстве CompilerOptions.

Если для вызова процесса компилятора требуется маркер безопасности Win32, задайте этот маркер в свойстве UserToken.

Чтобы сделать ссылку на исходный файл Win32 в скомпилированной сборке, укажите имя исходного файла Win32 в свойстве Win32Resource.

Чтобы указать уровень предупреждения, на котором следует прекратить компиляцию, задайте свойство WarningLevel как целое число, представляющее уровень предупреждения для прекращения компиляции. Вы также можете настроить компилятор для остановки компиляции, если возникают предупреждения, задав TreatWarningsAsErrors для свойства значение true.

В следующем примере кода демонстрируется компиляция исходного файла с помощью поставщика CodeDom, производного от класса CodeDomProvider.

public:
    static bool CompileCSharpCode(String^ sourceFile, String^ exeFile)
    {
        CSharpCodeProvider^ provider = gcnew CSharpCodeProvider();

        // Build the parameters for source compilation.
        CompilerParameters^ cp = gcnew 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);
            for each (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;
        }
    }
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;
    }
}
Public Shared Function CompileCSharpCode(sourceFile As String, _
    exeFile As String) As Boolean
    Dim provider As New CSharpCodeProvider()

    ' Build the parameters for source compilation.
    Dim cp As 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.
    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)
        For Each ce As CompilerError 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

Языки с начальной поддержкой

.NET предоставляет компиляторы кода и генераторы кода для следующих языков: C#, Visual Basic, C++и JScript. Поддержка CodeDOM может быть расширена на другие языки путем реализации генераторов и компиляторов кода для определенных языков.

См. также