Динамический вызов любой функции путем передачи имени функции в виде строки - PullRequest
25 голосов
/ 29 апреля 2009

Как мне автоматизировать процесс создания экземпляра и динамического выполнения его функции?

Спасибо

Редактировать: Нужна опция для передачи параметров тоже. Спасибо

Ответы [ 5 ]

46 голосов
/ 29 апреля 2009

Вы просто хотите вызвать конструктор без параметров для создания экземпляра? Тип также указан в виде строки, или вы можете сделать его универсальным методом? Например:

// All error checking omitted. In particular, check the results
// of Type.GetType, and make sure you call it with a fully qualified
// type name, including the assembly if it's not in mscorlib or
// the current assembly. The method has to be a public instance
// method with no parameters. (Use BindingFlags with GetMethod
// to change this.)
public void Invoke(string typeName, string methodName)
{
    Type type = Type.GetType(typeName);
    object instance = Activator.CreateInstance(type);
    MethodInfo method = type.GetMethod(methodName);
    method.Invoke(instance, null);
}

или

public void Invoke<T>(string methodName) where T : new()
{
    T instance = new T();
    MethodInfo method = typeof(T).GetMethod(methodName);
    method.Invoke(instance, null);
}
19 голосов
/ 17 июня 2009

Чтобы вызвать конструктор, Activator.CreateInstance сделает свое дело. Он имеет множество перегрузок, чтобы сделать вашу жизнь проще.

Если ваш конструктор без параметров :

object instance = Activator.CreateInstance(type)

Если вам нужно параметры :

object instance =  Activator.CreateInstance(type, param1, param2)

Чтобы вызвать метод, когда у вас есть объект Тип , вы можете вызвать GetMethod, чтобы получить метод , а затем Invoke (с параметрами или без параметров), чтобы вызвать его. Если вам это нужно, Invoke также выдаст вам возвращаемое значение функции, которую вы вызываете (или NULL, если это метод void),

Для более подробного примера (вставьте в консольное приложение и перейдите):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace Test
{
    public static class Invoker
    {
        public static object CreateAndInvoke(string typeName, object[] constructorArgs, string methodName, object[] methodArgs)
        {
            Type type = Type.GetType(typeName);
            object instance = Activator.CreateInstance(type, constructorArgs);

            MethodInfo method = type.GetMethod(methodName);
            return method.Invoke(instance, methodArgs);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Default constructor, void method
            Invoker.CreateAndInvoke("Test.Tester", null, "TestMethod", null);

            // Constructor that takes a parameter
            Invoker.CreateAndInvoke("Test.Tester", new[] { "constructorParam" }, "TestMethodUsingValueFromConstructorAndArgs", new object[] { "moo", false });

            // Constructor that takes a parameter, invokes a method with a return value
            string result = (string)Invoker.CreateAndInvoke("Test.Tester", new object[] { "constructorValue" }, "GetContstructorValue", null);
            Console.WriteLine("Expect [constructorValue], got:" + result);

            Console.ReadKey(true);
        }
    }

    public class Tester
    {
        public string _testField;

        public Tester()
        {
        }

        public Tester(string arg)
        {
            _testField = arg;
        }

        public void TestMethod()
        {
            Console.WriteLine("Called TestMethod");
        }

        public void TestMethodWithArg(string arg)
        {
            Console.WriteLine("Called TestMethodWithArg: " + arg);
        }

        public void TestMethodUsingValueFromConstructorAndArgs(string arg, bool arg2)
        {
            Console.WriteLine("Called TestMethodUsingValueFromConstructorAndArg " + arg + " " + arg2 + " " + _testField);
        }

        public string GetContstructorValue()
        {
            return _testField;
        }
    }
}
7 голосов
/ 29 апреля 2009

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

public void InvokeMethod(Type type, string methodName)
{
    object instance = Activator.CreateInstance(type);
    MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

    method.Invoke(instance, null);
}
3 голосов
/ 29 апреля 2009

Я думаю, что ваша проблема здесь слишком общая, я предлагаю решение с некоторыми допущениями.

Предположение: у вас есть typeName (строка), methodName (строка) и параметр (SomeType).

public static void InvokeMethod(string typeName, string methodName, SomeType objSomeType) {
      Type type = Type.GetType(typeName);
      if(type==null) {
        return;
      }
      object instance = Activator.CreateInstance(type); //Type must have a parameter-less contructor, or no contructor.   
      MethodInfo methodInfo =type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);
      if(methodInfo==null) {
        return;
      }
      methodInfo.Invoke(instance, new[] { objSomeType });  
    } 

дайте мне знать, если мои предположения неверны.

2 голосов
/ 03 октября 2016

Для динамической передачи параметров Здесь я взял params string [] args, потому что разные функции имеют разное количество параметров, поэтому.

public void Invoke(string typeName,string functionName,params string[] args)
    {

     Type type = Type.GetType(typeName);
     dynamic c=Activator.CreateInstance(type);
     //args contains the parameters(only string type)
     type.InvokeMember(functionName,BindingFlags.InvokeMethod,null,c,args);   

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