Il y a un groupe de méthodes privées dans ma classe, et je dois en appeler une dynamiquement en fonction d'une valeur d'entrée. Le code appelant et les méthodes cible se trouvent dans la même instance. Le code ressemble à ceci:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
Dans ce cas, GetMethod()
ne renverra pas de méthodes privées. Que BindingFlags
dois-je fournir pour GetMethod()
qu'il puisse localiser des méthodes privées?
c#
.net
reflection
private-methods
Jeromy Irvine
la source
la source
BindingFlags.NonPublic
private
méthode de non retour .. :(BindingFlags.Instance
ainsi queBindingFlags.NonPublic
pour les méthodes non statiques.non-static
etprivate
et la classe est héritée deSystem.Web.UI.Page
.. ça me fait quand même duper .. je n'ai pas trouvé la raison .. :(BindingFlags.FlattenHierarchy
vous permettra d'obtenir des méthodes des classes parentes sur votre instance.BindingFlags.NonPublic
ne retournera aucun résultat par lui-même. Il s'avère que le combiner avecBindingFlags.Instance
fait l'affaire.la source
internal
fonctionsEt si vous voulez vraiment vous mettre en difficulté, rendez-le plus facile à exécuter en écrivant une méthode d'extension:
Et l'utilisation:
la source
Microsoft a récemment modifié l'API de réflexion, rendant la plupart de ces réponses obsolètes. Les éléments suivants devraient fonctionner sur les plates-formes modernes (y compris Xamarin.Forms et UWP):
Ou comme méthode d'extension:
Remarque:
Si la méthode souhaitée se trouve dans une superclasse,
obj
leT
générique doit être explicitement défini sur le type de la superclasse.Si la méthode est asynchrone, vous pouvez l'utiliser
await (Task) obj.InvokeMethod(…)
.la source
GetDeclareMethod()
est destinée à être utilisée pour récupérer uniquement une méthode publique.Êtes-vous absolument sûr que cela ne peut pas se faire par héritage? La réflexion est la toute dernière chose à considérer lors de la résolution d'un problème, elle rend la refactorisation, la compréhension de votre code et toute analyse automatisée plus difficiles.
Il semble que vous devriez simplement avoir une classe DrawItem1, DrawItem2, etc. qui remplace votre dynMethod.
la source
La réflexion en particulier sur les membres privés est fausse
La réflexion des membres privés rompt le principe d' encapsulation et expose ainsi votre code aux éléments suivants:
Et si je dois quand même le faire?
Il y a donc des cas, lorsque vous dépendez d'un tiers ou que vous avez besoin d'une API non exposée, vous devez faire quelques réflexions. Certains l'utilisent également pour tester certaines classes dont ils sont propriétaires mais qui ne veulent pas modifier l'interface pour donner accès aux membres internes uniquement pour les tests.
Si vous le faites, faites-le bien
Pour atténuer le problème facile à casser, le mieux est de détecter toute rupture potentielle en testant des tests unitaires qui s'exécuteraient dans une version d'intégration continue ou autre. Bien sûr, cela signifie que vous utilisez toujours le même assembly (qui contient les membres privés). Si vous utilisez une charge dynamique et une réflexion, vous aimez jouer avec le feu, mais vous pouvez toujours attraper l'exception que l'appel peut produire.
Dans les versions récentes de .Net Framework, CreateDelegate battait d'un facteur 50 que MethodInfo invoquait:
draw
les appels seront environ 50 fois plus rapides que l'MethodInfo.Invoke
utilisationdraw
comme standardFunc
comme ça:Consultez ce post pour voir des références sur différentes invocations de méthodes
la source
Ne pourriez-vous pas simplement avoir une méthode Draw différente pour chaque type que vous souhaitez dessiner? Appelez ensuite la méthode Draw surchargée en passant l'objet de type itemType à dessiner.
Votre question ne précise pas si itemType fait réellement référence à des objets de types différents.
la source
Je pense que vous pouvez le passer là
BindingFlags.NonPublic
où c'est laGetMethod
méthode.la source
Appelle n'importe quelle méthode malgré son niveau de protection sur l'instance d'objet. Prendre plaisir!
la source
Lisez cette réponse (supplémentaire) (qui est parfois la réponse) pour comprendre où cela va et pourquoi certaines personnes dans ce fil se plaignent que "cela ne fonctionne toujours pas"
J'ai écrit exactement le même code que l'une des réponses ici . Mais j'avais toujours un problème. J'ai placé un point d'arrêt sur
Il a exécuté mais
mi == null
Et cela a continué comme ça jusqu'à ce que je "reconstruise" tous les projets impliqués. J'étais en train de tester un assemblage tandis que la méthode de réflexion était assise dans le troisième assemblage. C'était totalement déroutant, mais j'ai utilisé la fenêtre immédiate pour découvrir les méthodes et j'ai trouvé qu'une méthode privée que j'essayais de tester par unité avait un ancien nom (je l'ai renommé). Cela m'a dit que l'ancien assemblage ou PDB est toujours là même si le projet de test unitaire se construit - pour une raison quelconque, le projet qu'il n'a pas construit. "reconstruire" a fonctionné
la source
BindingFlags.NonPublic
la source