VB.Net:使用参数动态调用模块方法或例程 [英] VB.Net: Call a module Method or Routine dynamically with parameters

查看:31
本文介绍了VB.Net:使用参数动态调用模块方法或例程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用存储在带有参数的模块中的变量名运行一个方法:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆