基于字符串值在.NET中创建方法调用

基于字符串值在.NET中创建方法调用,.net,vb.net,method-call,.net,Vb.net,Method Call,现在,我有这样的代码: Private Sub ShowReport(ByVal reportName As String) Select Case reportName Case "Security" Me.ShowSecurityReport() Case "Configuration" Me.ShowConfigurationReport() Case "RoleUsers"

现在,我有这样的代码:

Private Sub ShowReport(ByVal reportName As String)
    Select Case reportName
        Case "Security"
            Me.ShowSecurityReport()
        Case "Configuration"
            Me.ShowConfigurationReport()
        Case "RoleUsers"
            Me.ShowRoleUsersReport()
        Case Else
            pnlMessage.Visible = True
            litMessage.Text = "The report name """ + reportName + """ is invalid."
    End Select
End Sub
有没有办法创建使用我的方法命名约定来简化事情的代码?下面是一些伪代码,它们描述了我要查找的内容:

Private Sub ShowReport(ByVal reportName As String)
    Try
        Call("Show" + reportName + "Report")
    Catch ex As Exception
        'method not found
    End Try
End Sub

您可以使用反射来实现这一点,但老实说,我认为这对于您的特定场景(即同一类中的代码和switch())来说过于复杂了

现在,如果您将应用程序设计为每个报表类型都有自己的程序集(类似于外接程序/插件体系结构)或捆绑在单个外部程序集中,那么您可以将报表程序集加载到appdomain中,然后使用反射来完成这类工作。

您可以使用。有关更多信息,请参阅

string ModuleName=“TestAssembly.dll”;
字符串TypeName=“TestClass”;
string MethodName=“TestMethod”;
Assembly myAssembly=Assembly.LoadFrom(ModuleName);
BindingFlags flags=(BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
模块[]myModules=myAssembly.GetModules();
foreach(myModules中的模块Mo)
{
if(Mo.Name==ModuleName)
{
Type[]myTypes=Mo.GetTypes();
foreach(myTypes中的Ty类型)
{
if(Ty.Name==TypeName)
{
MethodInfo[]myMethodInfo=Ty.GetMethods(标志);
foreach(myMethodInfo中的MethodInfo Mi)
{
if(Mi.Name==MethodName)
{
Object obj=Activator.CreateInstance(Ty);
对象响应=Mi.Invoke(obj,null);
}
}
}
}
}
}

使用反射。在
System.Reflection
命名空间中,您需要使用包含方法的类型上的
GetMethod(“methodName”)
来获取所需方法的
MethodInfo
对象

拥有
MethodInfo
对象后,可以使用对象实例和任何参数调用
.Invoke()

例如:

System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);

这是C#,应该很容易将其转换为VB。如果需要将参数传递到方法中,可以将它们添加到第二个参数中进行调用。

反射API允许您从方法中获取
MethodInfo
,然后对其动态调用
Invoke
。但对你来说,这太过分了

你应该考虑有一个由字符串索引的委派字典。

在C#中:

我的VB.Net快速端口:

Private Sub InvokeMethod(instance as object, methodName as string )
            'Getting the method information using the method info class
            Dim mi as MethodInfo = instance.GetType().GetMethod(methodName)

            'invoing the method
            'null- no parameter for the function [or] we can pass the array of parameters
            mi.Invoke(instance, Nothing)
End Sub

你可以使用反射。虽然就个人而言,我认为你应该坚持switch的说法

private void ShowReport(string methodName)
{
    Type type = this.GetType();
    MethodInfo method = type.GetMethod("Show"+methodName+"Report", BindingFlags.Public)
    method.Invoke(this, null);
}

对不起,我在做C。只需将其翻译为VB.NET。

如果我正确理解了这个问题,您必须使用反射来查找方法“show”+reportName,然后间接调用它:

半生不熟的例子:

Case "financial" :
{
   Assembly asm = Assembly.GetExecutingAssembly ();

    MethodInfo mi = asm.GetType ("thisClassType").GetMethod ("showFinancialReport");

   if (mi != null)
      mi.Invoke (null, new object[] {});

}
在那里插入您自己的逻辑,以组成要调用的方法的名称

有关详细信息,请参阅MethodInfo和Assembly的MSDN文档。

使用反射:

Type t = this.GetType();
try 
{
    MethodInfo mi = t.GetMethod(methodName, ...);

    if (mi != null)
    {
        mi.Invoke(this, parameters);
    }
} 

但我同意ago,最好不要更改原始代码;-)

你有一个更深层次的问题。你的字符串太重要了。谁在向你传递信息?你能让他们不那样做吗

坚持使用switch语句,因为它将内部实现(方法名称)与外部视图分离

假设您将其本地化为德语。你要重命名所有这些方法吗?

最接近你的问题的解决方案

您可以从这些报告中生成代理,并通过在哈希表中查找匹配字符串来调用它们:

Public Sub New()
    '...
    ReportTable.Add("Security", New ReportDelegate(AddressOf ShowSecurityReport))
    ReportTable.Add("Config", New ReportDelegate(AddressOf ShowConfigReport))
    ReportTable.Add("RoleUsers", New ReportDelegate(AddressOf ShowRoleUsersReport))
    '...
End Sub

Private Sub ShowSecurityReport()
    '...
End Sub

Private Sub ShowConfigReport()
    '...
End Sub

Private Sub ShowRoleUsersReport()
    '...
End Sub

Private Delegate Sub ReportDelegate()

Private ReportTable As New Dictionary(Of String, ReportDelegate)

Private Sub ShowReport(ByVal reportName As String)
    Dim ReportToRun As ReportDelegate
    If ReportTable.TryGetValue(reportName, ReportToRun) Then
        ReportToRun()
    Else
        pnlMessage.Visible = True
        litMessage.Text = "The report name """ + reportName + """ is invalid."
    End If
End Sub

通过这种方式,您可以添加任意数量的报告,您反映这些报告的能力以及反映的性能都不是问题。

在VB.Net MSVS 2015中为我工作

Dim tip As Type = GetType(MODULENAME)'if sub() or function() in module
        Dim method As MethodInfo = tip.GetMethod("MaxV") 'name of function (gets 2 params double type)
        Dim res As Double = 0 'temporary variable
        If (Not Nothing = method) Then 'if found function "MaxV"

            res = method.Invoke(Me, New Object() {10, 20})
        End If
        MsgBox(res.ToString())

你确定用字符串重写调用你函数的东西不会更容易吗?你可以用反射来做类似的事情,但我认为你的代码会更难看。你想要多少?我认为最好使用某种形式的命令模式,其中枚举字符串是命令的名称!非常正确。我想我们正在寻找好的方法来构建不太好的东西。我不确定你用字符串重写东西是什么意思。如果方法的数量至少超过20个,反射将是一个好的解决方案..30.没有驾驶,只是注意到这里的东西闻起来不太好。看见为什么是一根绳子?是用户输入吗?这个问题可以完全避免吗?是否应该?如果方法返回某个东西,该东西将存储在何处?调用将返回一个对象。只需将其转换为适当的类型即可。是否可以举一个示例,说明如何实现按字符串索引的委托字典并调用这些方法?
Dim tip As Type = GetType(MODULENAME)'if sub() or function() in module
        Dim method As MethodInfo = tip.GetMethod("MaxV") 'name of function (gets 2 params double type)
        Dim res As Double = 0 'temporary variable
        If (Not Nothing = method) Then 'if found function "MaxV"

            res = method.Invoke(Me, New Object() {10, 20})
        End If
        MsgBox(res.ToString())