Question

Comment automatiser le processus de création d'une instance et d'exécution dynamique de sa fonction?

Merci

Modifier: Besoin d'une option pour transmettre également les paramètres. Merci

Était-ce utile?

La solution

Voulez-vous simplement appeler un constructeur sans paramètre pour créer l'instance? Le type est-il également spécifié en tant que chaîne ou pouvez-vous en faire une méthode générique? Par exemple:

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

ou

public void Invoke<T>(string methodName) where T : new()
{
    T instance = new T();
    MethodInfo method = typeof(T).GetMethod(methodName);
    method.Invoke(instance, null);
}

Autres conseils

Pour appeler un constructeur, Activator.CreateInstance fera l'affaire. Il a un tas de surcharges pour vous rendre la vie plus facile.

Si votre constructeur est sans paramètre :

object instance = Activator.CreateInstance(type)

Si vous avez besoin de paramètres :

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

Pour appeler une méthode, une fois que vous avez le type objet, vous pouvez appeler GetMethod pour obtenir la méthode , puis Appeler (avec ou sans paramètres) pour l'invoquer. Si vous en avez besoin, Invoke vous donnera également la valeur de retour de la fonction que vous appelez (ou null si c'est une méthode void),

Pour un exemple un peu plus détaillé (coller dans une application console et aller):

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

En supposant que la méthode que vous souhaitez invoquer ne prend aucun paramètre:

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

Je pense que votre problème est un peu trop générique ici, je propose une solution avec certaines hypothèses ici.

Hypothèse: vous avez un typeName (string), un methodName (chaîne) et un paramètre (de 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 });  
    } 

laissez-moi savoir si mes hypothèses sont fausses.

Pour transmettre les paramètres de manière dynamique Ici, j'ai pris params string [] args, car différentes fonctions ont un nombre de paramètres différent, donc.

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

    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top