In meiner Klasse gibt es eine Gruppe privater Methoden, und ich muss eine dynamisch basierend auf einem Eingabewert aufrufen. Sowohl der aufrufende Code als auch die Zielmethode befinden sich in derselben Instanz. Der Code sieht folgendermaßen aus:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
In diesem Fall GetMethod()
werden keine privaten Methoden zurückgegeben. Was BindingFlags
muss ich bereitstellen, GetMethod()
damit private Methoden gefunden werden können?
c#
.net
reflection
private-methods
Jeromy Irvine
quelle
quelle
BindingFlags.NonPublic
private
Methode nicht zurückgeben .. :(BindingFlags.Instance
sowieBindingFlags.NonPublic
für nicht statische Methoden angeben .non-static
undprivate
und die Klasse wird von geerbtSystem.Web.UI.Page
.. es macht mich sowieso zum Narren .. ich habe den Grund nicht gefunden .. :(BindingFlags.FlattenHierarchy
können Sie Methoden aus übergeordneten Klassen zu Ihrer Instanz abrufen.BindingFlags.NonPublic
gibt keine Ergebnisse für sich zurück. Wie sich herausstellt, reicht es aus, es mit zu kombinierenBindingFlags.Instance
.quelle
internal
FunktionenUnd wenn Sie wirklich in Schwierigkeiten geraten möchten, vereinfachen Sie die Ausführung, indem Sie eine Erweiterungsmethode schreiben:
Und Verwendung:
quelle
Microsoft hat kürzlich die Reflection-API geändert, sodass die meisten dieser Antworten veraltet sind. Folgendes sollte auf modernen Plattformen (einschließlich Xamarin.Forms und UWP) funktionieren:
Oder als Erweiterungsmethode:
Hinweis:
Wenn die gewünschte Methode in einer Oberklasse von ist
obj
derT
Gattungs ausdrücklich auf die Art der Oberklasse festgelegt werden muss.Wenn die Methode asynchron ist, können Sie verwenden
await (Task) obj.InvokeMethod(…)
.quelle
GetDeclareMethod()
ist, dass nur eine öffentliche Methode abgerufen werden soll.Sind Sie absolut sicher, dass dies nicht durch Vererbung möglich ist? Reflexion ist das allerletzte, worauf Sie bei der Lösung eines Problems achten sollten. Sie erschwert das Refactoring, das Verständnis Ihres Codes und jede automatisierte Analyse.
Es sieht so aus, als ob Sie nur eine DrawItem1-, DrawItem2- usw. Klasse haben sollten, die Ihre dynMethod überschreibt.
quelle
Überlegungen insbesondere zu privaten Mitgliedern sind falsch
Private Mitglieder Reflexion bricht Verkapselung Prinzip und damit Ihr Code wie folgt ausgesetzt wird :
Was ist, wenn ich es trotzdem tun muss?
Es gibt Fälle, in denen Sie, wenn Sie von einem Dritten abhängig sind oder eine nicht exponierte API benötigen, einige Überlegungen anstellen müssen. Einige verwenden es auch, um einige Klassen zu testen, die sie besitzen, aber dass sie die Schnittstelle nicht ändern möchten, um den inneren Mitgliedern nur für Tests Zugriff zu gewähren.
Wenn Sie es tun, machen Sie es richtig
Um das Problem der leicht zu brechenden Probleme zu verringern, ist es am besten, potenzielle Unterbrechungen durch Tests in Komponententests zu erkennen, die in einem kontinuierlichen Integrations-Build oder dergleichen ausgeführt werden. Dies bedeutet natürlich, dass Sie immer dieselbe Assembly verwenden (die die privaten Mitglieder enthält). Wenn Sie eine dynamische Last und Reflexion verwenden, spielen Sie gerne mit dem Feuer, aber Sie können immer die Ausnahme abfangen, die der Anruf möglicherweise erzeugt.
In den neuesten Versionen von .Net Framework hat CreateDelegate die von MethodInfo aufgerufenen Faktoren um den Faktor 50 übertroffen:
draw
Anrufe sind etwa 50-mal schneller als dieMethodInfo.Invoke
Verwendungdraw
als StandardFunc
:Überprüfen Sie diesen Beitrag von mir , um Benchmark für verschiedene Methodenaufrufe zu sehen
quelle
Könnten Sie nicht einfach eine andere Zeichenmethode für jeden Typ haben, den Sie zeichnen möchten? Rufen Sie dann die überladene Draw-Methode auf, die das zu zeichnende Objekt vom Typ itemType übergibt.
Ihre Frage macht nicht klar, ob itemType wirklich auf Objekte unterschiedlicher Typen verweist.
quelle
Ich denke, Sie können es
BindingFlags.NonPublic
dort weitergeben, wo es dieGetMethod
Methode ist.quelle
Ruft eine Methode trotz ihrer Schutzstufe für die Objektinstanz auf. Genießen!
quelle
Lesen Sie diese (ergänzende) Antwort (das ist manchmal die Antwort), um zu verstehen, wohin das führt und warum sich einige Leute in diesem Thread beschweren, dass "es immer noch nicht funktioniert".
Ich habe genau den gleichen Code wie eine der Antworten hier geschrieben . Aber ich hatte immer noch ein Problem. Ich habe einen Haltepunkt gesetzt
Es wurde aber ausgeführt
mi == null
Und es ging so weiter, bis ich alle beteiligten Projekte "neu aufgebaut" habe. Ich habe eine Baugruppe getestet, während die Reflexionsmethode in der dritten Baugruppe saß. Es war total verwirrend, aber ich habe Immediate Window verwendet, um Methoden zu entdecken, und festgestellt, dass eine private Methode, die ich zum Unit-Test versuchte, einen alten Namen hatte (ich habe sie umbenannt). Dies sagte mir, dass alte Assemblys oder PDBs immer noch da draußen sind, selbst wenn Unit-Test-Projekte erstellt werden - aus irgendeinem Grund wurden Projekte, die getestet wurden, nicht erstellt. "Wiederaufbau" hat funktioniert
quelle
BindingFlags.NonPublic
quelle