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

时间:2008-09-25 16:03:52

标签: .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"
            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

12 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:3)

您可以使用反射来执行此操作,但说实话,我认为这会使您的特定方案(即同一类中的代码和switch())过于复杂。

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

答案 3 :(得分:3)

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

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

例如:

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

答案 4 :(得分:3)

Reflection API允许您从方法中获取MethodInfo,然后在其上动态调用Invoke。但在你的情况下,它是过度的。

您应该考虑使用由字符串索引的委托字典。

答案 5 :(得分: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。

答案 6 :(得分:0)

您可以使用System.Reflection。有关详细信息,请参阅this code project article

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);
                    }
                }
            }
        }
    }
}

答案 7 :(得分: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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

使用反射:

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

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

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

答案 10 :(得分: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

通过这种方式,您可以根据需要添加任意数量的报告,并且您能够反映这些报告以及反射的性能,这不是问题。

答案 11 :(得分: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())
相关问题