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

发布于 2024-07-05 08:34:15 字数 738 浏览 11 评论 0原文

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

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

Right now, I have code that looks something like this:

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

Is there any way to create code that would use my method naming conventions to simplify things? Here's some pseudocode that describes what I'm looking for:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

抱着落日 2024-07-12 08:34:15

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

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

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

这样您就可以添加任意数量的报告,并且您反映它们的能力以及反射的性能命中率都不会很高。这是一个问题。

The "Closest to your question" solution.

You could make delegates out of those reports, and call them by looking up the matching String in a 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

That way you can add as many reports as you like, and your ability to reflect them, and the perf hit of reflection, aren't an issue.

╭⌒浅淡时光〆 2024-07-12 08:34:15

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

If i understand the question correctly, you'll have to use Reflection to find the method "show" + reportName and then invoke it indirectly:

Half-baked example:

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

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

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

}

Insert your own logic there to make up the name for the method to call.

See MSDN documentation of MethodInfo and Assembly for details.

暖心男生 2024-07-12 08:34:15

使用反射:

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

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

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

Using reflection:

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

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

But I agree with ago, better not change your original code ;-)

缪败 2024-07-12 08:34:15

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

Python (and IronPython) can do this thing very easily. With .Net though, you need to use reflection.

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

My quick port to 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
酒废 2024-07-12 08:34:15

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

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

例如:

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

Use reflection. In the System.Reflection namespace you need to get a MethodInfo object for the method you want, using GetMethod("methodName") on the type containing the method.

Once you have the MethodInfo object, you can call .Invoke() with the object instance and any parameters.

For Example:

System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);
孤独陪着我 2024-07-12 08:34:15

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

You can use reflection. Though personally, I think you should just stick with the switch statement.

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

Sorry, I'm doing C#. Just translate it to VB.NET.

也只是曾经 2024-07-12 08:34:15

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

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

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

You've got a deeper problem. Your strings are too important. Who is passing you strings? can you make them not do that?

Stick with the switch statement, as it decouples your internal implementation (method names) from your external view.

Suppose you localize this to German. You gonna rename all those methods?

审判长 2024-07-12 08:34:15

反射 API 允许您从方法获取 MethodInfo,然后动态调用它的 Invoke。 但就你的情况而言,这太过分了。

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

Reflection API allows you to get a MethodInfo from a method, then calling Invoke dynamically on it. But it is overkill in your case.

You should consider having a dictionary of delegates indexed by strings.

埖埖迣鎅 2024-07-12 08:34:15

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

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

You could use reflection to do this but to be honest I think it's overcomplicating things for your particular scenario i.e. code and switch() in the same class.

Now, if you had designed the app to have each report type in its own assembly (kinda like an add-in/plugin architecture) or bundled in a single external assembly then you could load the reporting assemblie(s) into an appdomain and then use reflection to do this kinda thing.

吾性傲以野 2024-07-12 08:34:15
Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
    method.Invoke(this, null);
}

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

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

This is C#, should be easy enough to turn it into VB. If you need to pass parameter into the method, they can be added in the 2nd argument to Invoke.

残龙傲雪 2024-07-12 08:34:15

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

Worked for me in 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())
擦肩而过的背影 2024-07-12 08:34:15

您可以使用 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);
                    }
                }
            }
        }
    }
}

You can, using System.Reflection. See this code project article for more information.

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);
                    }
                }
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文