Hay un grupo de métodos privados en mi clase, y necesito llamar a uno dinámicamente en función de un valor de entrada. Tanto el código de invocación como los métodos de destino están en la misma instancia. El código se ve así:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
En este caso, GetMethod()
no devolverá métodos privados. ¿ BindingFlags
Qué necesito suministrar para GetMethod()
que pueda localizar métodos privados?
c#
.net
reflection
private-methods
Jeromy Irvine
fuente
fuente
BindingFlags.NonPublic
private
método de no devolución .. :(BindingFlags.Instance
, así comoBindingFlags.NonPublic
para los métodos no estáticos.non-static
yprivate
y la clase se hereda deSystem.Web.UI.Page
... me hace tonto de todos modos ... no encontré la razón ... :(BindingFlags.FlattenHierarchy
le permitirá obtener métodos de clases primarias para su instancia.BindingFlags.NonPublic
no devolverá ningún resultado por sí solo. Resulta que combinarlo conBindingFlags.Instance
hace el truco.fuente
internal
funciones tambiénY si realmente quieres meterte en problemas, haz que sea más fácil de ejecutar escribiendo un método de extensión:
Y uso:
fuente
Microsoft modificó recientemente la API de reflexión haciendo que la mayoría de estas respuestas sean obsoletas. Lo siguiente debería funcionar en plataformas modernas (incluidos Xamarin.Forms y UWP):
O como un método de extensión:
Nota:
Si el método deseado está en una superclase de
obj
laT
genérico se debe establecer explícitamente al tipo de la superclase.Si el método es asíncrono, puede usarlo
await (Task) obj.InvokeMethod(…)
.fuente
GetDeclareMethod()
está destinado a ser utilizado para recuperar solo un método público.¿Estás absolutamente seguro de que esto no se puede hacer a través de la herencia? La reflexión es lo último que debe tener en cuenta al resolver un problema, dificulta la refactorización, la comprensión de su código y cualquier análisis automatizado.
Parece que solo debería tener una clase DrawItem1, DrawItem2, etc. que anule su dynMethod.
fuente
La reflexión especialmente sobre los miembros privados es incorrecta
La reflexión de miembros privados rompe el principio de encapsulación y, por lo tanto, expone su código a lo siguiente:
¿Qué pasa si debo hacerlo de todos modos?
Hay casos en los que, cuando depende de un tercero o necesita alguna API no expuesta, debe reflexionar. Algunos también lo usan para probar algunas clases que poseen pero que no quieren cambiar la interfaz para dar acceso a los miembros internos solo para las pruebas.
Si lo haces, hazlo bien
Para mitigar el problema fácil de romper, lo mejor es detectar cualquier ruptura potencial probando en pruebas unitarias que se ejecutarían en una compilación de integración continua o similar. Por supuesto, significa que siempre usa el mismo ensamblado (que contiene los miembros privados). Si usa una carga dinámica y una reflexión, le gusta jugar con fuego, pero siempre puede detectar la Excepción que puede producir la llamada.
En las versiones recientes de .Net Framework, CreateDelegate supera en un factor 50 la invocación MethodInfo:
draw
las llamadas serán aproximadamente 50 veces más rápidas que elMethodInfo.Invoke
usodraw
como un estándarFunc
como ese:Consulte esta publicación mía para ver el punto de referencia sobre invocaciones de diferentes métodos
fuente
¿No podría simplemente tener un método de dibujo diferente para cada tipo que desea dibujar? Luego llame al método Draw sobrecargado pasando el objeto de tipo itemType para dibujar.
Su pregunta no deja en claro si itemType realmente se refiere a objetos de diferentes tipos.
fuente
Creo que se puede pasar que
BindingFlags.NonPublic
cuando se es elGetMethod
método.fuente
Invoca cualquier método a pesar de su nivel de protección en la instancia del objeto. ¡Disfrutar!
fuente
Lea esta respuesta (complementaria) (que a veces es la respuesta) para comprender a dónde va esto y por qué algunas personas en este hilo se quejan de que "todavía no funciona"
Escribí exactamente el mismo código que una de las respuestas aquí . Pero aún tenía un problema. Puse un punto de quiebre en
Se ejecutó pero
mi == null
Y continuó con este comportamiento hasta que "reconstruí" todos los proyectos involucrados. Estaba probando un ensamblaje mientras el método de reflexión estaba en el tercer ensamblaje. Fue totalmente confuso, pero utilicé la ventana Inmediato para descubrir métodos y descubrí que un método privado que intenté probar en la unidad tenía un nombre antiguo (lo cambié de nombre). Esto me dijo que el antiguo ensamblaje o PDB todavía está disponible, incluso si el proyecto de prueba de unidad se construye, por alguna razón el proyecto que prueba no se construyó. "reconstruir" funcionó
fuente
BindingFlags.NonPublic
fuente