Type type = GetType();
MethodInfo method = type.GetMethod("Show"+reportName+"Report");
if (method != null)
{
method.Invoke(this, null);
}
Это - C#, должно быть достаточно легко превратить его в VB. Если необходимо передать параметр в метод, они могут быть добавлены в 2-м аргументе для Вызова.
API Reflection позволяет Вам получать a MethodInfo
из метода, затем звоня Invoke
динамично на нем. Но это - излишество в Вашем случае.
Необходимо считать наличие словаря делегатов индексированным строками.
У Вас есть более глубокая проблема. Ваши строки слишком важны. Кто передает, Вы представляете в виде строки? можно ли заставить их не сделать этого?
Палка с оператором переключения, поскольку это отделяет Вашу внутреннюю реализацию (имена методов) от Вашего внешнего представления.
Предположим, что Вы локализуете это немецкому языку. Вы собираетесь переименовать все те методы?
Используйте отражение. В System.Reflection
пространство имен необходимо получить a MethodInfo
объект для метода Вы хотите, с помощью GetMethod("methodName")
на типе, содержащем метод.
После того как Вы имеете MethodInfo
объект, можно звонить .Invoke()
с экземпляром объекта и любыми параметрами.
Например:
System.Reflection.MethodInfo method = this.GetType().GetMethod("foo");
method.Invoke(this, null);
Вы могли использовать отражение, чтобы сделать это, но быть честным я думаю, что оно сверхусложняет вещи для Вашего конкретного сценария т.е. кода и переключателя () в том же классе.
Теперь, если Вы разработали приложение, чтобы иметь каждый тип отчета в его собственном блоке (своего рода как add-in/plugin архитектура) или связались в единственном внешнем блоке затем, Вы могли загрузить создание отчетов assemblie (s) в appdomain и затем использовать отражение, чтобы сделать такого рода вещь.
Используя отражение:
Type t = this.GetType();
try
{
MethodInfo mi = t.GetMethod(methodName, ...);
if (mi != null)
{
mi.Invoke(this, parameters);
}
}
Но я соглашаюсь с назад, лучше не изменяют Ваш исходный код ;-)
Если я понимаю вопрос правильно, необходимо будет использовать Отражение, чтобы найти метод "шоу" + reportName и затем вызвать его косвенно:
Непродуманный пример:
Case "financial" :
{
Assembly asm = Assembly.GetExecutingAssembly ();
MethodInfo mi = asm.GetType ("thisClassType").GetMethod ("showFinancialReport");
if (mi != null)
mi.Invoke (null, new object[] {});
}
Вставьте свою собственную логику там для составления названия метода для вызова.
См. документацию MSDN MethodInfo и блока для деталей.
Можно использовать отражение. Хотя лично, я думаю, что необходимо просто придерживаться оператора переключения.
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.
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
Вы можете, с помощью Системы. Отражение. См. эту статью проекта кода для получения дополнительной информации.
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);
}
}
}
}
}
}
"Самый близкий к Вашему вопросу" решение.
Вы могли сделать делегатов из тех отчетов и назвать их путем поиска соответствующей строки в Хеш-таблице:
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
Тем путем можно добавить, поскольку много отчетов как Вам угодно и способность отразить их и хит перфекта отражения, не являются проблемой.