10

现在,我的代码看起来像这样:

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
4

12 回答 12

18
Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
    method.Invoke(this, null);
}

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

于 2008-09-25T16:08:28.627 回答
5

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

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

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

于 2008-09-25T16:56:39.057 回答
3

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

现在,如果您将应用程序设计为在其自己的程序集中(有点像插件/插件架构)或捆绑在单个外部程序集中的每个报告类型,那么您可以将报告程序集加载到应用程序域中,然后使用反射来做这种事情。

于 2008-09-25T16:06:19.847 回答
3

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

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

例如:

System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);
于 2008-09-25T16:08:17.283 回答
3

反射 API 允许您MethodInfo从方法中获取一个,然后对其进行动态调用Invoke。但在你的情况下它是矫枉过正的。

您应该考虑拥有一个按字符串索引的委托字典。

于 2008-09-25T16:10:07.640 回答
2

您可以使用反射。尽管就个人而言,我认为您应该坚持使用 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。

于 2008-09-25T16:10:23.240 回答
0

您可以使用System.Reflection。有关详细信息,请参阅此代码项目文章

string ModuleName = "TestAssembly.dll";
string TypeName = "TestClass";
string MethodName = "TestMethod";

Assembly myAssembly = Assembly.LoadFrom(ModuleName);

BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | 
  BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);

Module [] myModules = myAssembly.GetModules();
foreach (Module Mo in myModules) 
{
 if (Mo.Name == ModuleName) 
     {
     Type[] myTypes = Mo.GetTypes();
     foreach (Type Ty in myTypes)
         {
        if (Ty.Name == TypeName) 
            {
            MethodInfo[] myMethodInfo = Ty.GetMethods(flags);
            foreach(MethodInfo Mi in myMethodInfo)
                {
                if (Mi.Name == MethodName) 
                    {
                    Object obj = Activator.CreateInstance(Ty);
                    Object response = Mi.Invoke(obj, null);
                    }
                }
            }
        }
    }
}
于 2008-09-25T16:07:31.640 回答
0

Python(和 IronPython)可以很容易地做到这一点。但是,使用 .Net,您需要使用反射。

在 C# 中:http: //www.dotnetspider.com/resources/4634-Invoke-me-ods-dynamically-using-reflection.aspx

我快速移植到 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
于 2008-09-25T16:10:08.777 回答
0

如果我正确理解了这个问题,您将不得不使用反射找到方法“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 文档。

于 2008-09-25T16:14:37.550 回答
0

使用反射:

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

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

但我同意之前,最好不要更改您的原始代码;-)

于 2008-09-25T16:15:02.917 回答
0

“最接近您的问题”的解决方案。

您可以从这些报告中创建代表,并通过在 Hashtable 中查找匹配的字符串来调用它们:

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

这样,您可以添加任意数量的报告,并且您反映它们的能力以及反射的性能都不是问题。

于 2008-09-25T18:07:31.833 回答
0

在 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())
于 2019-02-04T12:39:40.590 回答