我已经在这篇文章中找到了对这个问题的回答:https://stackoverflow.com/a/14711110/1764912
但我的下一个查询是,当我尝试在此动态代码中声明DataTable或MsgBox时,它给出了一个错误“未定义类型'DataTable'”和“未定义类型'MsgBox'”是。如果我使用动态代码中的第一行添加导入:
Imports System.Data
或
Imports System.Data.DataTable
或者如果我在GenerateScript()函数中使用以下任何代码(请参考https://stackoverflow.com/a/14711110/1764912获取GenerateScript()函数)
Dim importDataNameSpace As String = GetType(DataTable).Namespace
Dim codeArray() As String = New String() {"Imports " & importDataNameSpace & Environment.NewLine & code}
或者如果我使用
Dim codeArray() As String = New String() {"Imports System.Data" & Environment.NewLine & code}
或
Dim codeArray() As String = New String() {"Imports System.Data.DataTable" & Environment.NewLine & code}
在上述所有情况下,它都会给我一个错误“System.Data不包含任何公共成员或找不到”。
答案 0 :(得分:6)
除非您首先引用库,否则导入名称空间不会对您有任何帮助。如果未引用库,则您导入的命名空间实际上将为空。
正如其他人在上面的评论中提到的那样,仅仅因为您在项目中引用了System.Data.dll
库,这并不意味着它也会被您动态编译的程序集引用。每个程序集都需要直接引用它需要的所有程序集。动态编译的程序集也不例外。
通过CompilerParameters.ReferencedAssemblies.Add
方法将引用添加到动态程序集中。您可以在我对您链接的问题的回答中看到一个示例。在该示例中,我将动态程序集引用返回到主程序集,以便它可以使用IScript
接口。但是,您可以根据需要添加任意数量的引用。要添加对System.Data.dll
的引用,您可以这样做:
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
由于System.Data.dll
程序集位于GAC中,因此您无需指定完整路径。另请注意,为了使用DataTable
,您还需要添加对System.Xml.dll
的引用。一旦运行代码,就会发现它。
因此,如果您定义了上述方法,并且您定义了以下接口:
Public Interface IScript
Function DoWork() As String
End Interface
然后,你可以这样称呼它:
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"