Подтвердить что ты не робот

Вызовите методы, используя имена в С#

У меня есть несколько "заданий" в моем приложении, где каждое задание содержит список методов, которые ему нужно вызвать, а также его параметры. По существу, список, содержащий следующий объект, называется:

string Name;
List<object> Parameters;

Итак, в основном, когда выполняется задание, я хочу перечислить этот список и вызвать соответствующие методы. Например, если у меня есть метод, подобный следующему:

TestMethod(string param1, int param2)

Мой объект метода будет выглядеть следующим образом:

Name = TestMethod
Parameters = "astring", 3

Можно ли это сделать? Я думаю, что размышление будет ключевым здесь.

4b9b3361

Ответ 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;
   ...
}

Если вы знаете, что у вас есть только отличный набор возможностей для вызова, почему бы не просто настроить себя раньше времени?