Load VB.net code from .txt file and execute it on fly using System.CodeDom.Compiler
codedom, vb.net
Solution
Importing namespaces does nothing for you unless you first also reference the library. If the library isn't referenced, then the namespace that you're importing will effectively be empty.
As others have mentioned in the comments above, just because you have the `System.Data.dll` library referenced in your project, that doesn't mean that it is also referenced by the assembly that you are dynamically compiling. Each assembly needs to directly reference all of the assemblies that it needs. Dynamically compiled assemblies are no exception.
References are added to the dynamic assembly via the `CompilerParameters.ReferencedAssemblies.Add` method. You can see an example of that in my answer to the question that you linked to. In that example, I had the dynamic assembly reference back to the main assembly so that it could use the `IScript` interface. You can, however, add as many references as you like. To also add a reference to `System.Data.dll`, you could do it like this:
Public Function GenerateScript(code As String) As IScript
Using provider As New VBCodeProvider()
Dim parameters As New CompilerParameters()
parameters.GenerateInMemory = True
parameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location)
parameters.ReferencedAssemblies.Add("System.Data.dll")
parameters.ReferencedAssemblies.Add("System.Xml.dll")
Dim interfaceNamespace As String = GetType(IScript).Namespace
Dim codeArray() As String = New String() {"Imports " & interfaceNamespace & Environment.NewLine & code}
Dim results As CompilerResults = provider.CompileAssemblyFromSource(parameters, codeArray)
If results.Errors.HasErrors Then
Throw New Exception("Failed to compile script")
Else
Return CType(results.CompiledAssembly.CreateInstance("Script"), IScript)
End If
End Using
End Function
Since the `System.Data.dll` assembly is in the GAC, you don't need to specify a full path. Notice also, that in order to use `DataTable`, you'll also need to add a reference to `System.Xml.dll`. You'd find that out as soon as you ran the code.
So, if you had the above method defined, and you had the following interface defined:
Public Interface IScript
Function DoWork() As String
End Interface
Then, you'd be able to call it like this:
Dim builder As New StringBuilder()
builder.AppendLine("Public Class Script")
builder.AppendLine(" Implements IScript")
builder.AppendLine(" Public Function DoWork() As String Implements IScript.DoWork")
builder.AppendLine(" Dim table As New System.Data.DataTable()")
builder.AppendLine(" table.TableName = ""Hello World""")
builder.AppendLine(" Return table.TableName")
builder.AppendLine(" End Function")
builder.AppendLine("End Class")
Dim script As IScript = GenerateScript(builder.ToString())
Console.WriteLine(script.DoWork()) ' Outputs "Hello World"
Problem
I have found answer to this question already in this post : https://stackoverflow.com/a/14711110/1764912 But my next query is, When I try to declare either a DataTable or MsgBox inside this dynamic code, it give me an error that "Type 'DataTable' is not defined" and "Type 'MsgBox' is not defined" is. If I add imports using either first line in dynamic code as : ``` Imports System.Data ``` or ``` Imports System.Data.DataTable ``` or if I use any of the following code in GenerateScript() function (Please refer https://stackoverflow.com/a/14711110/1764912 for GenerateScript() function) ``` Dim importDataNameSpace As String = GetType(DataTable).Namespace Dim codeArray() As String = New String() {"Imports " & importDataNameSpace & Environment.NewLine & code} ``` or if I use ``` Dim codeArray() As String = New String() {"Imports System.Data" & Environment.NewLine & code} ``` or ``` Dim codeArray() As String = New String() {"Imports System.Data.DataTable" & Environment.NewLine & code} ``` In all above cases, it give me an error "System.Data does not contain any public members or couldn't found".