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

问题描述 投票:10回答:12

现在,我有一些代码看起来是这样的:

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
.net vb.net method-call
12个回答
18
投票
Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
    method.Invoke(this, null);
}

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


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

这样,只要你喜欢,你可以添加任意多的报告,您反映他们的能力和反射的PERF命中,是不是一个问题。


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

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())

5
投票

你已经有了一个更深层次的问题。你的字符串是太重要了。谁是你传递字符串?你可以让他们不这样做呢?

与switch语句棒,因为它能够消除你的外观你的内部实现(方法名)。

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


3
投票

反射API允许你从一个方法MethodInfo,然后在其上调用动态Invoke。但它是矫枉过正你的情况。

你应该考虑具有字符串索引代表的字典。


3
投票

你可以使用反射来做到这一点,但说实话,我认为这是过于复杂的事情在同一类的特定情况,即代码和开关()。

现在,如果你设计了该应用在每个报告类型在其自己的组件(有点像一个加载/插件架构),或在一个单一的外部组件捆绑在一起,那么你可以在报告assemblie(S)加载到一个AppDomain,然后使用反射来做到这一点有点儿事。


3
投票

使用反射。在System.Reflection命名空间,你需要得到你想要的方法MethodInfo对象,使用GetMethod("methodName")上包含方法的类型。

一旦你的MethodInfo对象,你可以调用.Invoke()与对象实例和任何参数。

例如:

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

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。


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

0
投票

如果我理解正确的问题,你将不得不使用反射来查找方法“秀” +所以reportName,然后调用它间接地:

半生不熟的例子:

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

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

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

}

插入自己的逻辑有弥补的方法来调用的名称。

详情请参阅的MethodInfo和大会的MSDN文档。


0
投票

使用反射:

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

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

但我同意前,最好不要改变你原来的代码;-)

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.