从 .txt 文件加载 VB.net 代码并使用 System.CodeDom.Compiler 即时执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21379926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Load VB.net code from .txt file and execute it on fly using System.CodeDom.Compiler
提问by SMultani
I have found answer to this question already in this post : https://stackoverflow.com/a/14711110/1764912
我已经在这篇文章中找到了这个问题的答案: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 :
但是我的下一个查询是,当我尝试在此动态代码中声明 DataTable 或 MsgBox 时,它给我一个错误,即“未定义类型 'DataTable'”和“未定义类型 'MsgBox'”。如果我使用动态代码中的第一行添加导入:
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/1764912for GenerateScript() function)
或者如果我在 GenerateScript() 函数中使用以下任何代码(有关 GenerateScript() 函数,请参阅https://stackoverflow.com/a/14711110/1764912)
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".
在上述所有情况下,它给我一个错误“System.Data 不包含任何公共成员或找不到”。
回答by Steven Doggart
Importing namespaces does nothing for you unless you first also referencethe 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.dlllibrary 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.
正如其他人在上面的评论中提到的,仅仅因为您System.Data.dll在项目中引用了库,这并不意味着它也被您动态编译的程序集引用。每个程序集都需要直接引用它需要的所有程序集。动态编译的程序集也不例外。
References are added to the dynamic assembly via the CompilerParameters.ReferencedAssemblies.Addmethod. 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 IScriptinterface. 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:
通过该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
Since the System.Data.dllassembly 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.
由于System.Data.dll程序集位于 GAC 中,因此您无需指定完整路径。另请注意,为了使用DataTable,您还需要添加对 的引用System.Xml.dll。一旦你运行代码,你就会发现这一点。
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"

