最终用户定义的代码 - 如何使用现有的 类 和 ExecutingAssembly 中的对象

end-user defined code - how to use existing classes and objects from the ExecutingAssembly

我有一个类似于 OP 在 How to load an internal class in end-user compiled code ? (advanced) 中的 winform,其中我有一个文本框,它将成为最终用户代码的来源,当我点击按钮。

以下是部分代码(其中大部分是从 How to load an internal class in end-user compiled code ? (advanced) 复制而来的:

Imports System
Imports System.CodeDom.Compiler
Imports System.Reflection
Imports System.Text

Public Class Form1

Private Sub ExecuteB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteB.Click
    Dim Code As String = Me.CodeToExec.Text

    Dim CompilerResult As CompilerResults
    CompilerResult = Compile(Code)
End Sub

Public Function Compile(ByVal Code As String) As CompilerResults
    Dim CodeProvider As New VBCodeProvider
    Dim CodeCompiler As System.CodeDom.Compiler.CodeDomProvider = CodeDomProvider.CreateProvider("VisualBasic")

    Dim Parameters As New System.CodeDom.Compiler.CompilerParameters
    Parameters.GenerateExecutable = False
    Parameters.ReferencedAssemblies.Add("System.dll")
    Parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")
    Parameters.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")

    Dim CompilerResult As CompilerResults = CodeCompiler.CompileAssemblyFromSource(Parameters, Code)

    If CompilerResult.Errors.HasErrors Then
        CompileTB.Clear()
        For i = 0 To CompilerResult.Errors.Count - 1
            CompileTB.AppendText(CompilerResult.Errors(i).ErrorText & vbCrLf)
        Next
        Return Nothing
    Else
        Return CompilerResult
    End If
End Function

End Class

我的控件是:CodeToExec 是用户放置自定义代码的文本框,CompileTB 是另一个列出错误的文本框,ExecuteB 是按钮。我的程序中还有其他 classes 和对象,这里是我想使用的 classes 之一:

Public Class ExceptionCriteria

Private _CriteriaName As String
Public Property CriteriaName As String
    Get
        CriteriaName = _CriteriaName
    End Get
    Set(value As String)
        _CriteriaName = value
    End Set
End Property

Private _RuleSet As List(Of String)
Public Property RuleSet As List(Of String)
    Get
        RuleSet = _RuleSet
    End Get
    Set(value As List(Of String))
        _RuleSet = value
    End Set
End Property

Private _SerializationFilePath As String
Public Property SerializationFilePath As String
    Get
        SerializationFilePath = _SerializationFilePath
    End Get
    Set(value As String)
        _SerializationFilePath = value
    End Set
End Property

Public Sub AddRule(newRule As String)
    If IsNothing(_RuleSet) Then
        _RuleSet = New List(Of String)
    End If
    _RuleSet.Add(newRule)
End Sub

End Class

这是我想要 use/set 在 Form1 class 中的成员之一:

Public comparisondate As Date = #2/20/2015#

我的问题是,我想 access/modify 执行程序集中的对象、成员和属性,并根据那里的自定义 classes 创建新对象。我该怎么做?

我碰到了答案,我缺少的是

Parameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location)

然后我只需要将程序和成员共享。希望这也能帮助到和我一样刚好遇到同样问题并路过此页的新手。

如果你想使用现有的 类,你应该知道如何(自)引用以及如何传递参数。这是一个小例子:

  1. 不要忘记在生成的代码中Imports YourProjectName

  2. 例子Class做所有必要的事情

    Imports System.CodeDom.Compiler
    Imports System.Reflection
    
    Public Class MyHelloCompiler
        Private Shared                  _ass As Assembly
        Private Shared            _YourClass As Type
        Private Shared           _YourMethod As MethodInfo
        Private Shared    _YourClassInstance As Object
    
        Public Sub New()
            'Code to compile and instantiate the compiled class for later use:
            Dim opt As New CompilerParameters _
                                   (Nothing, String.Empty, False)
            opt.GenerateExecutable = False
            opt.GenerateInMemory = True
            ' Following is the important self reference
            opt.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location)
    
            Console.WriteLine (MyCodeToCompile)
    
            Dim res As CompilerResults = New VBCodeProvider().CompileAssemblyFromSource (opt, MyCodeToCompile)
            _ass =  res.CompiledAssembly
            _YourClass = _ass.GetType ("MyExampleClass")
            _YourMethod = _YourClass.GetMethod ("MyExampleProperty")
            _YourClassInstance =  Activator.CreateInstance ( _YourClass)
        End Sub
    
        Public Class MyExampleClass()
            Public Property MyExampleProperty as String
        End Class
    
        Public Function RunCompiledCodeWithParams( _
              instanceOfExampleClass as MyExampleClass) as String
            Dim params As Object() = New Object() {instanceOfExampleClass}
            Return CStr(_YourMethod.Invoke(_YourClassInstance, params))
        End Function
    
        Private Function MyCodeToCompile() as String
            Return _
            "Imports System" & vbCrLf & _
            "Imports YourProjectName" & vbCrLf & _
            "Public Class ClassToCompile" & vbCrLf & _
            "    Public Shared Function GetExampleProperty(prmExampleClassInstance as MyExampleClass) as String" & vbcrlf & _
            "        Return prmExampleClassInstance.MyExampleProperty" & vbcrlf & _
            "    End Function" & vbcrlf & _
            "End Class"
        End Function
    End Class
    
  3. 在上面调用:

    '....
    Dim MyTestCompile As MyHelloCompiler = New MyHelloCompiler
    Dim MyDummyClass  As MyExampleClass  = New MyExampleClass
    MyDummyClass.MyExampleProperty   = "I am the property value"
    
    Dim MyResult as String = _
        MyTestCompile.RunCompiledCodeWithParams(MyDummyClass)
    '....