您可以使用反射来创建一个委托在Module
方法。我会将创建的代表装入Dictionary(Of String, Action(Of Int32))
。
Action(Of Int32)
被选择,因为它匹配您指定的子程序采用整数参数的签名。
假设你有一个像这样定义的Module
:
Module SomeModule
Public Sub Sub1(arg As Int32)
Console.WriteLine("Sub1: {0}", arg)
End Sub
Public Sub Sub2(arg As Int32)
Console.WriteLine("Sub2: {0}", arg)
End Sub
End Module
我们创建并代表存储在字典中。
Private methods As New Dictionary(Of String, Action(Of Int32))
Sub LoadMethods()
Dim modType As Type = GetType(SomeModule)
Dim mi As Reflection.MethodInfo
mi = modType.GetMethod("Sub1", BindingFlags.Static Or BindingFlags.Public)
methods.Add(mi.Name, CType(mi.CreateDelegate(GetType(Action(Of Int32))), Action(Of Int32)))
mi = modType.GetMethod("Sub2", BindingFlags.Static Or BindingFlags.Public)
methods.Add(mi.Name, CType(mi.CreateDelegate(GetType(Action(Of Int32))), Action(Of Int32)))
End Sub
您可以检索和调用委托这样的:
methods("Sub1")(123)
methods("Sub2")(456)
编辑:我有时会使事情复杂化。该LoadMethods
方法可以在不反射就像这样:
Sub LoadMethods()
methods.Add("Sub1", New Action(Of Int32)(AddressOf SomeModule.Sub1))
methods.Add("Sub2", New Action(Of Int32)(AddressOf SomeModule.Sub1))
End Sub
编辑2:基于编辑质疑和评论如下。
编辑:为了使它很简单,我需要VBA的等价的:
Application.Run module_name.sub_name PARAM
您需要首先从含有其提取Module
类型基于输入名称的组装。然后你可以检索如上所示的MethodInfo
。以下示例假定模块包含在正在执行的程序集中,并且已执行最少的检查。它将要求您提供模块名称,方法名称和数组正确类型的方法参数。在真实世界的场景中,可能需要接收一串参数并执行某种类型的动态类型转换,以基于调用MethodInfo.GetParameters来构建typedArgs
数组。
Private Shared Sub Exec(moduleName As String, methodName As String, typedArgs As Object())
Dim asm As Reflection.Assembly = Assembly.GetExecutingAssembly
Dim modType As Type = asm.GetType(String.Format("{0}.{1}", asm.GetName.Name, moduleName))
If modType IsNot Nothing Then
Dim mi As Reflection.MethodInfo
mi = modType.GetMethod(methodName, BindingFlags.Static Or BindingFlags.Public)
If mi IsNot Nothing Then
mi.Invoke(Nothing, typedArgs)
End If
End If
End Sub
用法示例:Exec("SomeModule", "Sub1", New Object() {123})
谢谢,但是这需要我添加的每个新Sub和每一个新的模块LoadMethods(我不想维护)。我希望VB.Net等价于VBA:Application.Run module_name.sub_name参数 –
@BassemLhm,我提供了一个基本模板来完成修改的需求,作为对此答案的编辑。 – TnTinMn
非常感谢。唯一改变的是用asm.GetName.Name中的下划线替换空格... –