【问题标题】:How to pass a reference to a form to dynamically compiled code如何将对表单的引用传递给动态编译的代码
【发布时间】:2017-02-23 16:36:31
【问题描述】:

我正在尝试为我的 VB .Net 应用程序创建一个应用程序脚本环境。我在应用程序中有一个名为 Project 的表单类型。我想要做的是在 Project 表单上动态编译(即 Eval)VB .Net 代码。此动态代码始终具有 Main 函数。 Main 的参数之一是对调用 Project 表单的引用。这是评估代码:

    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。但是,当引用调用程序集项目表单执行代码时,出现以下错误:

在程序集“LaserTrak V4 软件,版本=4.507.3992.19399,文化=中性,PublicKeyToken=null”上运行评估。 评估编译代码时出错。错误是: 调用的目标已引发异常。 内部异常是: System.MissingMemberException:未找到类型“Project”的公共成员“CompilationErrors”。 在 Microsoft.VisualBasic.CompilerServices.Symbols.Container.GetMembers(String& MemberName, Boolean ReportErrors) 在 Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(对象实例,类型类型,字符串成员名称,对象 [] 参数,字符串 [] 参数名称,类型 [] 类型参数,布尔 [] CopyBack) 在 Translation.Main(Assembly& MyAssembly, Project& MyProjectForm)

我的猜测是 Main 过程没有对调用程序集活动 Project 表单的“可信”访问。我如何给它访问权限? 谢谢你的帮助。

【问题讨论】:

  • 你有没有得到解决方案没有编译错误

标签: .net vb.net


【解决方案1】:

我猜 CompilationErrors 不是公共成员?是朋友吗?还是私人的?还是受保护?

如果它是 Friend 成员,您可以使用 InternalsVisibleToAttribute,否则,您将无法通过这种方式访问​​它。

如果您使用的是 C# 4.0,则可以假设使用允许私有成员访问的 DynamicObject...但这是另一回事...

【讨论】:

    【解决方案2】:

    CompilationErrors 是 Project 表单上的一个文本框。我忘记将其 Modifiers 属性设置为 Public,因为我是个白痴 ;-)。

    【讨论】:

    • 不回答,更好的评论?恕我直言。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 2020-06-22
    • 2013-08-04
    • 2018-03-30
    • 2020-11-04
    • 2012-07-14
    • 2021-11-08
    相关资源
    最近更新 更多