Вызовите методы, используя имена в С#
У меня есть несколько "заданий" в моем приложении, где каждое задание содержит список методов, которые ему нужно вызвать, а также его параметры. По существу, список, содержащий следующий объект, называется:
string Name;
List<object> Parameters;
Итак, в основном, когда выполняется задание, я хочу перечислить этот список и вызвать соответствующие методы. Например, если у меня есть метод, подобный следующему:
TestMethod(string param1, int param2)
Мой объект метода будет выглядеть следующим образом:
Name = TestMethod
Parameters = "astring", 3
Можно ли это сделать? Я думаю, что размышление будет ключевым здесь.
Ответы
Ответ 1
Конечно, вы можете сделать это следующим образом:
public class Test
{
public void Hello(string s) { Console.WriteLine("hello " + s); }
}
...
{
Test t = new Test();
typeof(Test).GetMethod("Hello").Invoke(t, new[] { "world" });
// alternative if you don't know the type of the object:
t.GetType().GetMethod("Hello").Invoke(t, new[] { "world" });
}
Второй параметр Invoke() - это массив объекта, содержащий все параметры, передаваемые вашему методу.
Предполагая, что все методы принадлежат одному классу, вы можете иметь способ этого класса:
public void InvokeMethod(string methodName, List<object> args)
{
GetType().GetMethod(methodName).Invoke(this, args.ToArray());
}
Ответ 2
Если вы используете .NET Framework 4, посмотрите dynamic, иначе GetMethod
, а затем вызовите Invoke
из MethodInfo
.
Ответ 3
NuGet на помощь! PM> Install-Package dnpextensions
Как только у вас есть этот пакет в вашем проекте, все объекты теперь должны иметь расширение .InvokeMethod()
, которое будет принимать имя метода как строку и любое количество параметров.
Это технически использует "магические строки" для имен методов, поэтому, если вы хотите сильно набирать словарь методов, вы можете сделать ключи типа MethodInfo и получить их как это...
MethodInfo[] methodInfos = typeof(MyClass).GetMethods();
И тогда вы можете сделать что-то вроде этого...
var methods = new Dictionary<MethodInfo, Object[]>();
foreach (var item in methods)
item.key.Invoke(null, item.value);
// 'null' may need to be an instance of the object that
// you are calling methods on if these are not static methods.
Или вы могли бы сделать некоторые изменения в вышеупомянутом блоке, используя упомянутые ранее dnpextensions.
Ответ 4
Используйте MethodBase.Invoke(). Должен работать до .NET 2.0 с System.Reflection
.
Ответ 5
Если вы используете необходимость прибегать к размышлениям, возможно, лучший способ выполнить вашу задачу. Это может занять немного больше архитектуры, но это возможно.
Помните, что иметь больше кода - это не плохо, особенно когда он дополняет читаемость и управляемость вашего кода. Отражение трудно понять для большинства, и вы теряете большую часть своей безопасности типа времени компиляции. В вашем примере вы могли бы просто уйти с оператором switch и отдельными объектами для каждого метода, который планировали вызывать. например.
// Have some object hold the type of method it plans on calling.
enum methodNames
{
Method1,
Method2
}
...
class someObject
{
internal methodNames methodName {get; set;}
internal object[] myParams;
}
...
// Execute your object based on the enumeration value it references.
switch(someObject1.methodName)
{
case Method1:
Test.Method1(Int32.Parse(someObject1.myParams[0].ToString),someObject1.myParams[1].ToString());
break;
...
}
Если вы знаете, что у вас есть только отличный набор возможностей для вызова, почему бы не просто настроить себя раньше времени?