vb.net - microsoft codedom providers dotnetcompilerplatform 1.0 0
Cargue el código de VB.net del archivo.txt y ejecútelo en tiempo real con System.CodeDom.Compiler. (1)
He encontrado la respuesta a esta pregunta en esta publicación: https://stackoverflow.com/a/14711110/1764912
Pero mi siguiente consulta es: cuando trato de declarar un DataTable o un MsgBox dentro de este código dinámico, me da un error de que "Type ''DataTable'' no está definido" y "Type ''MsgBox'' no está definido". Si agrego importaciones utilizando la primera línea en código dinámico como:
Imports System.Data
o
Imports System.Data.DataTable
o si uso cualquiera de los siguientes códigos en la función GenerateScript () (consulte https://stackoverflow.com/a/14711110/1764912 para la función GenerateScript ())
Dim importDataNameSpace As String = GetType(DataTable).Namespace
Dim codeArray() As String = New String() {"Imports " & importDataNameSpace & Environment.NewLine & code}
o si uso
Dim codeArray() As String = New String() {"Imports System.Data" & Environment.NewLine & code}
o
Dim codeArray() As String = New String() {"Imports System.Data.DataTable" & Environment.NewLine & code}
En todos los casos anteriores, me da un error "System.Data no contiene ningún miembro público o no se pudo encontrar".
La importación de espacios de nombres no hace nada por usted a menos que primero también haga referencia a la biblioteca. Si no se hace referencia a la biblioteca, entonces el espacio de nombre que está importando estará efectivamente vacío.
Como han mencionado otros en los comentarios anteriores, el hecho de que tenga la biblioteca System.Data.dll
que se hace referencia en su proyecto, eso no significa que el ensamblado al que hace referencia la compilación dinámica también haga referencia. Cada ensamblaje necesita referenciar directamente todos los ensamblajes que necesita. Los ensamblados dinámicamente compilados no son una excepción.
Las referencias se agregan al ensamblaje dinámico a través del método CompilerParameters.ReferencedAssemblies.Add
. Puede ver un ejemplo de eso en mi respuesta a la pregunta a la que se vinculó. En ese ejemplo, tuve la referencia de ensamblaje dinámico en el ensamblaje principal para que pudiera usar la interfaz IScript
. Sin embargo, puede agregar tantas referencias como desee. Para agregar también una referencia a System.Data.dll
, puede hacerlo así:
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
Como el ensamblado System.Data.dll
está en el GAC, no necesita especificar una ruta completa. También tenga en cuenta que para usar DataTable
, también deberá agregar una referencia a System.Xml.dll
. Lo descubrirías tan pronto como ejecutaras el código.
Entonces, si tenía definido el método anterior, y tenía definida la siguiente interfaz:
Public Interface IScript
Function DoWork() As String
End Interface
Entonces, podrías llamarlo así:
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"