Как передать импортированные пространства имен в CompileAssemblyFromSource

Я пытаюсь загрузить исходный файл VB в память. Однако файл VB предполагает, что Project, с которым он связан, имеет некоторые глобальные "Импортированные пространства имен", определенные на уровне проекта. Эта функция VB позволяет отдельным файлам опускать оператор Imports (Использование в C#) для каждого отдельного файла.

    Dim sourceCode As String = ""
    'sourceCode &= "Imports System.Data" & vbNewLine
    sourceCode &= "Class Foo" & vbNewLine
    sourceCode &= "Sub Print()" & vbNewLine
    sourceCode &= "Dim dtbl As DataTable" & vbNewLine
    sourceCode &= "System.Console.WriteLine(""Hello, world!"")" & vbNewLine
    sourceCode &= "End Sub" & vbNewLine
    sourceCode &= "End Class" & vbNewLine

    Dim compiler As New Microsoft.VisualBasic.VBCodeProvider

    Dim params As New Compiler.CompilerParameters
    params.ReferencedAssemblies.Add("System.dll")
    params.ReferencedAssemblies.Add("System.Data.dll")
    params.ReferencedAssemblies.Add("System.Xml.dll")
    params.GenerateInMemory = True
    params.GenerateExecutable = False

    Dim results As Compiler.CompilerResults = compiler.CompileAssemblyFromSource(params, sourceCode)

    If results.Errors.Count > 0 Then
        For Each compileError In results.Errors
            Console.WriteLine(compileError.ToString)
        Next
        Return
    End If

    Dim assembly = results.CompiledAssembly

Строка 2 закомментирована. Если я раскомментирую это и добавлю оператор Imports, код работает нормально. Это также работает нормально, если я изменяю "Dim dtbl As DataTable" на "Dim dtbl As System.Data.DataTable".

Вместо того, чтобы раскомментировать эту строку кода, есть ли способ передать этот оператор Imports в компилятор или параметры, как если бы это был глобальный проект Imported Namespace?

Я мог бы просто добавить этот оператор Imports в начало каждого файла, который я прочитал. Но если он уже есть, я получаю сообщение об ошибке, что оператор Imports дублируется. Я мог бы выполнить некоторую проверку Regex, чтобы увидеть, существует ли уже оператор Imports, но я бы хотел максимально использовать инфраструктуру System.CodeDom.

2 ответа

Решение

ОК, нет ответов:(Я думаю, что фреймворк не делает то, что я хотел бы сделать. Вот мое хакерское решение, использующее Regex для внедрения оператора Imports.

sourceCode = AddImportsIfNeeded(sourceCode, "System.Data")


Private Function AddImportsIfNeeded(ByVal sourceCode As String, ByVal namespaceToImport As String) As String

    If Not Regex.IsMatch(sourceCode, "^\s*Imports\s+" & Regex.Escape(namespaceToImport) & "\s*$", RegexOptions.Multiline) Then
        Return "Imports " & namespaceToImport & vbNewLine & sourceCode
    End If
    Return sourceCode

End Function

Обратите внимание, что это не будет работать, если файл содержит операторы Option (например, Option Strict On). Операторы импорта должны быть ниже операторов выбора.

Вы можете импортировать пространства имен, используя CompilerOptions собственность CompilerParameters учебный класс. Добавьте эту строку в ваш пример, и компилятор больше не будет генерировать ошибку компилятора:

params.CompilerOptions = "/import:System.Data"
Другие вопросы по тегам