Reputation: 824
I'm trying to load a VB source file into memory. However, the VB file assumes that Project it is associated to has some global "Imported Namespaces" defined at the project level. This VB feature allows individual files to omit the Imports statement (Using in C#) on every single file.
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
Line 2 is commented out. If I uncomment this and add the Imports statement the code works fine. It also works fine if I change "Dim dtbl As DataTable" to "Dim dtbl As System.Data.DataTable".
Instead of uncommenting that line of code, is there a way to feed this Imports statement into the compiler or params as if it was a global project level Imported Namespace?
I could just add this Imports statement to the top of each file I read in. But if it is already there then I get an error that the Imports statement is duplicate. I could do some Regex checking to see if the Imports statement is already there, but I'd like to leverage the System.CodeDom framework as much as possible.
Upvotes: 2
Views: 719
Reputation: 801
You can import namespaces using the CompilerOptions
property of the CompilerParameters
class. Add this line to your example, and the compiler will no longer generate a compiler error:
params.CompilerOptions = "/import:System.Data"
Upvotes: 0
Reputation: 824
OK, no answers :( I guess the framework doesn't do what I'd like to do. Here is my hacky solution using Regex to inject the Imports statement.
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
Note that this won't work if the file contains Option statements (like Option Strict On). The Imports statements must go below the Option statements.
Upvotes: 1