Создайте вызов метода в .NET на основе строкового значения - PullRequest
10 голосов
/ 25 сентября 2008

Прямо сейчас у меня есть код, который выглядит примерно так:

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 ]

18 голосов
/ 25 сентября 2008
Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
    method.Invoke(this, null);
}

Это C #, должно быть достаточно легко превратить его в VB. Если вам нужно передать параметр в метод, его можно добавить во 2-й аргумент Invoke.

5 голосов
/ 25 сентября 2008

У вас есть более глубокая проблема. Ваши строки слишком важны. Кто передает тебе струны? вы можете заставить их не делать этого?

Придерживайтесь оператора switch, поскольку он отделяет вашу внутреннюю реализацию (имена методов) от внешнего вида.

Предположим, вы локализовали это на немецкий. Ты собираешься переименовать все эти методы?

3 голосов
/ 25 сентября 2008

Reflection API позволяет получить MethodInfo из метода, а затем динамически вызывать Invoke для него. Но это излишне в вашем случае.

Вы должны рассмотреть вопрос о наличии словаря делегатов, проиндексированных по строкам.

3 голосов
/ 25 сентября 2008

Используйте отражение. В пространстве имен System.Reflection необходимо получить объект MethodInfo для нужного метода, используя GetMethod("methodName") для типа, содержащего метод.

Получив объект MethodInfo, вы можете вызвать .Invoke() с экземпляром объекта и любыми параметрами.

Например:

System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);
3 голосов
/ 25 сентября 2008

Вы можете использовать рефлексию, чтобы сделать это, но, честно говоря, я думаю, что это усложняет вещи для вашего конкретного сценария, то есть кода и switch () в одном классе.

Теперь, если вы спроектировали приложение так, чтобы каждый тип отчета имел свою собственную сборку (вроде архитектуры надстроек / плагинов) или был объединен в одну внешнюю сборку, вы можете загрузить сборку (-ы) отчетности в appdomain, а затем используйте рефлексию, чтобы сделать такую ​​вещь.

2 голосов
/ 25 сентября 2008

Вы можете использовать отражение. Хотя лично я думаю, что вы должны просто придерживаться инструкции 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 голосов
/ 04 февраля 2019

Работал для меня в 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())
0 голосов
/ 25 сентября 2008

Решение "Ближайший к вашему вопросу".

Вы можете сделать делегатов из этих отчетов и вызвать их, просмотрев соответствующую строку в 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

Таким образом, вы можете добавить столько отчетов, сколько захотите, и ваша способность их отражать, а также удачное отражение, не проблема.

0 голосов
/ 25 сентября 2008

Использование отражения:

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

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

Но я согласен с тем, лучше не менять исходный код; -)

0 голосов
/ 25 сентября 2008

Если я правильно понял вопрос, вам придется использовать Reflection, чтобы найти метод "show" + reportName, а затем косвенно вызвать его:

Пример полуготовности:

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

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

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

}

Вставьте туда свою собственную логику, чтобы составить имя для вызываемого метода.

Подробнее см. Документацию MSDN для MethodInfo и Assembly.

...