130 votes

Appelez la méthode statique avec réflexion

J'ai plusieurs classes statiques dans l'espace de noms mySolution.Macros comme

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}

Donc ma question est de savoir comment il sera possible d'appeler ces méthodes avec l'aide de la réflexion?

Si les méthodes où ne PAS être statique, alors je pourrais faire quelque chose comme:

var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );

foreach (var tempClass in macroClasses)
{
   var curInsance = Activator.CreateInstance(tempClass);
   // I know have an instance of a macro and will be able to run it

   // using reflection I will be able to run the method as:
   curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
}

Je tiens à garder mes classes statiques. Comment vais-je être en mesure de faire quelque chose de similaire avec des méthodes statiques?

En bref j'aime à les appeler tous les Exécuter des méthodes de toutes les classes statiques qui sont dans l'espace de noms mySolution.Les Macros.

169voto

Lee Points 63849

Comme l'indique la documentation de MethodInfo.Invoke , le premier argument est ignoré pour les méthodes statiques afin que vous puissiez simplement passer null.

 foreach (var tempClass in macroClasses)
{
   // using reflection I will be able to run the method as:
   tempClass.GetMethod("Run").Invoke(null, null);
}
 

Comme le souligne le commentaire, vous pouvez vous assurer que la méthode est statique lors de l'appel de GetMethod :

 tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
 

20voto

Loudenvier Points 2390

Vous pourriez vraiment, vraiment, vraiment optimiser votre code beaucoup en payant le prix de la création de la déléguer qu'une seule fois (il y a aussi, pas besoin d'instancier la classe pour appeler une méthode statique). J'ai fait quelque chose de très similaire, et je viens de mettre en cache un délégué pour le "Run" de la méthode avec l'aide d'une classe d'aide :-). Il ressemble à ceci:

static class Indent{    
     public static void Run(){
         // implementation
     }
     // other helper methods
}

static class MacroRunner {

    static MacroRunner() {
        BuildMacroRunnerList();
    }

    static void BuildMacroRunnerList() {
        macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Namespace.ToUpper().Contains("MACRO"))
            .Select(t => (Action)Delegate.CreateDelegate(
                typeof(Action), 
                null, 
                t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Action> macroRunners;

    public static void Run() {
        foreach(var run in macroRunners)
            run();
    }
}

Il est BEAUCOUP plus rapide de cette façon.

Si votre signature de la méthode est différente de l'Action que vous pourriez remplacer le type jette et typeof de l'Action à tout de l'Action et Func types génériques, ou déclarer votre Délégué et de l'utiliser. Ma propre implémentation utilise la touche Func pour de jolis objets d'impression:

static class PerttyPrinter {

    static PrettyPrinter() {
        BuildPrettyPrinterList();
    }

    static void BuildPrettyPrinterList() {
        printers = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(x => x.Name.EndsWith("PrettyPrinter"))
            .Select(t => (Func<object, string>)Delegate.CreateDelegate(
                typeof(Func<object, string>), 
                null, 
                t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
            .ToList();
    }

    static List<Func<object, string>> printers;

    public static void Print(object obj) {
        foreach(var printer in printers)
            print(obj);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X