Динамический вызов любой функции путем передачи имени функции в виде строки.

StackOverflow https://stackoverflow.com/questions/801070

Вопрос

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

Спасибо

Редактировать:Также нужна возможность передавать параметры.Спасибо

Это было полезно?

Решение

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

// 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);
}

Другие советы

Чтобы вызвать конструктор, Активатор.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;
        }
    }
}

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

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);
}

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

Предположение:у вас есть имя типа (строка), имя метода (строка) и параметр (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 });  
    } 

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

Чтобы динамически передавать параметры, я взял 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);   

    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top