Вызовите методы, используя имена в C # - PullRequest
17 голосов
/ 24 июня 2011

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

string Name;
List<object> Parameters;

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

TestMethod(string param1, int param2)

Мой метод объекта будет выглядеть так:

Name = TestMethod
Parameters = "astring", 3

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

Ответы [ 5 ]

40 голосов
/ 24 июня 2011

Конечно, вы можете сделать это так:

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 () - это массив Object, содержащий все параметры, передаваемые вашему методу.

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

public void InvokeMethod(string methodName, List<object> args)
{
    GetType().GetMethod(methodName).Invoke(this, args.ToArray());
}
1 голос
/ 24 июня 2011

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, которые я упоминал ранее.

1 голос
/ 24 июня 2011

Если вы используете .NET Framework 4, посмотрите на dynamic , в противном случае GetMethod и затем вызовите Invoke из MethodInfo.

0 голосов
/ 24 июня 2011

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

Помните, что иметь больше кода не так уж и плохо, особенно если он дополняет удобочитаемость и управляемость вашего кода. Отражение трудно понять большинству, и вы теряете большую часть безопасности типов времени компиляции. В вашем примере вы, вероятно, могли бы просто получить инструкцию 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;
   ...
}

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

0 голосов
/ 24 июня 2011

Использовать MethodBase.Invoke () . Должен работать до .NET 2.0 с System.Reflection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...