我正在尝试为VB .Net应用程序创建应用程序脚本环境。我在应用程序中有一个名为项目的表单类型。我想要做的是在项目表单上动态编译(即Eval)VB .Net代码。此动态代码始终具有 Main 功能。 Main 的一个参数是对调用 Project 表单的引用。这是Eval代码:
Public Function Eval(ByVal vbCode As String, ByRef MyAssembly As System.Reflection.Assembly, ByRef ProjectForm As Project) As ArrayList
Dim Provider As VBCodeProvider = CodeDomProvider.CreateProvider("VisualBasic")
Dim CompParams As CompilerParameters = New CompilerParameters
Dim CResult As CompilerResults
Dim EvalAssy As System.Reflection.Assembly
Dim InstanceObject As Object
Dim InstanceType As Type
Dim InstanceMI As MethodInfo
Dim CompError As CompilerError
Dim NumberOfErrors As Integer = 0
Dim ReturnValues As New ArrayList
Dim SkipAssembly As Boolean = False
Dim DebugTextBox As TextBox = ProjectForm.CompilationErrors
Dim DebugFilename As String = ProjectForm.DebugFile
Dim StatusBar As ToolStripStatusLabel = ProjectForm.MyMainForm.MessageToolStripStatusLabel
'Result = MsgBox("HMMM: " & CodeDomProvider.IsDefinedLanguage("VisualBasic").ToString(), MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "HMMM")
If Not DebugTextBox Is Nothing Then
DebugTextBox.Text &= "Running Eval On Assembly """ & MyAssembly.FullName & """." & vbCrLf
End If
CompParams.ReferencedAssemblies.Add("system.dll")
CompParams.ReferencedAssemblies.Add("system.xml.dll")
CompParams.ReferencedAssemblies.Add("system.data.dll")
CompParams.ReferencedAssemblies.Add("System.Windows.Forms.dll")
' Pass Myself In
CompParams.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly.Location)
CompParams.CompilerOptions = "/t:library"
CompParams.GenerateInMemory = True
CResult = Provider.CompileAssemblyFromSource(CompParams, vbCode)
For Each CompError In CResult.Errors
If Not CompError.IsWarning Then
' "Real Error"
NumberOfErrors += 1
End If
ReturnValues.Add("Error " & CompError.ErrorNumber & " On Line " & CompError.Line & ": " & CompError.ErrorText)
Next
If NumberOfErrors = 0 Then
Try
EvalAssy = CResult.CompiledAssembly
InstanceObject = EvalAssy.CreateInstance("Translation")
InstanceType = InstanceObject.GetType()
InstanceMI = InstanceType.GetMethod("Main")
InstanceMI.Invoke(InstanceObject, New Object() {MyAssembly, ProjectForm})
'InstanceMI.Invoke(InstanceObject, BindingFlags.Default, Nothing, New Object() {MyAssembly, ProjectForm}, System.Globalization.CultureInfo.CurrentCulture)
Catch Ex As Exception
If Ex.InnerException Is Nothing Then
WriteDebugMsg(DebugTextBox, "Error Evaling Compiled Code. The Error Is """ & Ex.Message)
Else
WriteDebugMsg(DebugTextBox, "Error Evaling Compiled Code. The Error Is:" & vbCrLf & Ex.Message & vbCrLf & "Inner Exception Is:" & vbCrLf & Ex.InnerException.ToString)
End If
End Try
End If
Return ReturnValues
End Function
动态(Eval)代码中的Main函数是:
Imports System
Imports System.Xml
Imports System.Data
Imports Microsoft.VisualBasic
Imports System.Reflection
Imports System.Diagnostics
Imports System.IO
Imports System.Windows.Forms
Imports System.Collections
Imports System.Text
Imports UniversalTranslator
Public Sub Main(ByRef MyAssembly As System.Reflection.Assembly, ByRef MyProjectForm As Project)
' Create functions needed to parse assembly here and in subroutines called from here
Me.ProjectForm = MyProjectForm
DebugFile = ProjectForm.DebugFile ' Set Global Debug Filename Variable
DebugTB = ProjectForm.CompilationErrors
' Initialize Log Files And Debug Textboxes
If Dir(DebugFile,FileAttribute.Normal) > "" Then
Kill(DebugFile)
End If
If Not DebugTB is Nothing Then
DebugTB.Text = ""
end if
RecurseAssemblyForms(MyAssembly,AddressOf OutputControlInfo)
End Sub
一切都很好。已编译的代码将MyProjectForm识别为调用程序集中的类型Project。但是,当代码通过对调用程序集项目表单的引用执行时,我收到以下错误:
在装配上运行Eval“LaserTrak V4软件,版本= 4.507.3992.19399,Culture = neutral,PublicKeyToken = null”。 错误评估编译代码。错误是: 调用的目标抛出了异常。 内部例外是: System.MissingMemberException:找不到类型“Project”上的公共成员“CompilationErrors”。 在Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName,Boolean ReportErrors) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance,Type Type,String MemberName,Object [] Arguments,String [] ArgumentNames,Type [] TypeArguments,Boolean [] CopyBack) 在Translation.Main(Assembly& MyAssembly,Project& MyProjectForm)
我的猜测是 Main 过程没有对受调用程序集活动 Project 表单的“可信”访问权限。我如何给它访问权限? 谢谢你的帮助。
答案 0 :(得分:0)
我猜CompilationErrors不是公共成员?这是朋友吗?还是私人?还是受保护?
如果它是朋友成员,您可以使用InternalsVisibleToAttribute,否则,您将无法以这种方式访问它。
如果您使用的是C#4.0,您可以假设使用允许私有成员访问的DynamicObject ...但这是另一个故事......
答案 1 :(得分:0)
CompilationErrors 是“项目”表单上的文本框。我忘了把它的Modifiers属性设置为Public,因为我是个白痴;-)。