VB.Net:使用参数动态调用模块方法或例程 [英] VB.Net: Call a module Method or Routine dynamically with parameters
问题描述
我想使用存储在带有参数的模块中的变量名运行一个方法:
Dim subName as String = "sub1"将参数调暗为整数 = 123sub1(param) <- 我想使用 **subName** 字符串运行它
我不想使用 Select
Case
因为方法在许多不同的模块中,我不想维护一个 select-case 函数.>
我查找了 CallByName
但它似乎只适用于类.当涉及到模块时,我不知道如何设置对象ObjectRef
:
公共函数CallByName(ByVal ObjectRef As System.Object,ByVal ProcName As String,ByVal UseCallType As CallType, ByVal Args() As Object) As Object
有没有办法在 VB.Net 中做到这一点?
为了使它真正简单,我需要相当于 VBA 的:
Application.Run module_name.sub_name 参数
您可以使用反射为 Module
中的方法创建委托.我会将创建的委托加载到 Dictionary(Of String, Action(Of Int32))
中.
Action(Of Int32)
是因为它与您指定的带整数参数的子例程的签名相匹配.
假设你有一个 Module
定义如下:
Module SomeModulePublic Sub Sub1(arg As Int32)Console.WriteLine("Sub1: {0}", arg)结束子Public Sub Sub2(arg As Int32)Console.WriteLine("Sub2: {0}", arg)结束子终端模块
现在在字典中创建和存储委托.
Private methods As New Dictionary(Of String, Action(Of Int32))子加载方法()Dim modType As Type = GetType(SomeModule)Dim mi As Reflection.MethodInfomi = modType.GetMethod("Sub1", BindingFlags.Static 或 BindingFlags.Public)methods.Add(mi.Name, CType(mi.CreateDelegate(GetType(Action(Of Int32))), Action(Of Int32)))mi = modType.GetMethod("Sub2", BindingFlags.Static 或 BindingFlags.Public)methods.Add(mi.Name, CType(mi.CreateDelegate(GetType(Action(Of Int32))), Action(Of Int32)))结束子
您可以像这样检索和调用委托:
methods("Sub1")(123)方法(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))结束子
编辑 2:基于对下面问题和评论的编辑.
<块引用>为了使它真正简单,我需要相当于 VBA 的:
Application.Run module_name.sub_name 参数
您需要首先根据输入的名称从其包含的程序集中提取 Module
类型.然后您可以检索如上所示的 MethodInfo
.下面的示例假定模块包含在执行程序集中并已实现最少的检查.它将要求您提供模块名称、方法名称和正确键入的方法参数数组.在实际场景中,它可能需要获取一串参数并执行某种类型的动态类型转换以基于调用 MethodInfo.GetParameters.
Private Shared Sub Exec(moduleName As String, methodName As String, typedArgs As Object())Dim asm As Reflection.Assembly = Assembly.GetExecutingAssemblyDim modType As Type = asm.GetType(String.Format("{0}.{1}", asm.GetName.Name, moduleName))如果 modType IsNot Nothing 那么Dim mi As Reflection.MethodInfomi = modType.GetMethod(methodName, BindingFlags.Static 或 BindingFlags.Public)如果我不是什么,那么mi.Invoke(Nothing, typedArgs)万一万一结束子
示例用法:Exec("SomeModule", "Sub1", New Object() {123})
I want to run a Method using a variable name that is stored in a Module with a parameter:
Dim subName as String = "sub1"
Dim param as Integer = 123
sub1(param) <- I want to run this using the **subName** string
I don't want to use Select
Case
because the Methods are in many different modules and I don't want to maintain a select-case function.
I looked up CallByName
but it seems this only works for Classes. I can't figure out how to set the object ObjectRef
when it comes to Modules :
Public Function CallByName(ByVal ObjectRef As System.Object,ByVal ProcName As String,ByVal UseCallType As CallType, ByVal Args() As Object) As Object
Is there a way to do this in VB.Net?
Edit: To make it really simple, I need the equivalent of VBA's:
Application.Run module_name.sub_name param
You can use reflection to create a delegate to the methods in the Module
. I would load the created delegates into a Dictionary(Of String, Action(Of Int32))
.
Action(Of Int32)
is chosen because it matches the signature you specified of a subroutine taking an integer parameter.
Assume you have a Module
defined like this:
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
Now to create and store the delegates in a dictionary.
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
You can retrieve and invoke the delegate like this:
methods("Sub1")(123)
methods("Sub2")(456)
Edit: I sometimes makes things to complicated. The LoadMethods
method can be done without reflection like this:
Sub LoadMethods()
methods.Add("Sub1", New Action(Of Int32)(AddressOf SomeModule.Sub1))
methods.Add("Sub2", New Action(Of Int32)(AddressOf SomeModule.Sub1))
End Sub
Edit 2: Based on edit to question and comment below.
Edit: To make it really simple, I need the equivalent of VBA's:
Application.Run module_name.sub_name param
You will need to first extract the Module
type from its containing assembly based on the entered name. Then you can retrieve the MethodInfo
as shown above. The following example assumes that the module is contained in the executing assembly and has minimal checks implemented. It will require you to provide the module name, method name and an array properly typed method arguments. In a real world scenario, it would probably need to take a string of the arguments and perform some type of dynamic type casting to build up the typedArgs
array based on calling MethodInfo.GetParameters.
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
Example usage: Exec("SomeModule", "Sub1", New Object() {123})
这篇关于VB.Net:使用参数动态调用模块方法或例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!