Comment automatiser le processus de création d'une instance et l'exécution dynamique de sa fonction?
Merci
Edit: besoin d'une option pour passer les paramètres aussi. Merci
Voulez-vous simplement appeler un constructeur sans paramètre pour créer l'instance? Le type est-il également spécifié sous forme de 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);
}
Pour invoquer un constructeur, Activator.CreateInstance fera l'affaire. Il a un tas de surcharges pour vous faciliter la vie.
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 l'objet Type , vous pouvez appeler GetMethod
pour obtenir la méthode , puis - Invoke
(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 échantillon légèrement plus détaillé (collez dans une application console et c'est parti):
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 fournis ici une solution avec certaines hypothèses.
Hypothèse: vous avez un typeName (chaîne), 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 });
}
faites-moi savoir si mes hypothèses sont fausses.
Pour passer les paramètres dynamiquement Ici, j'ai pris params string [] args, car différentes fonctions ont un nombre différent de paramètres.
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);
}