2010-04-22 5 views
33

Estoy jugando con la API de reflexión C#. Puedo cargar fácilmente Type información de clases, métodos, etc. en un ensamblado, sin embargo, ahora me pregunto cómo puedo cargar y leer el código dentro de un método?¿Puedo usar el reflejo para inspeccionar el código en un método?

+0

Lo es el escenario que hace que esto sea útil? Rompe uno de los inquilinos fundamentales de OO que es encapsulación. Pero, además, el código como IL no es realmente lo mismo. – DevelopingChris

+8

@DevelopingChris: si está escribiendo una herramienta de depuración o análisis de código, puede ser útil poder cargar un ensamblaje y analizar el cuerpo de un método. Esto es, de hecho, lo que hacen las herramientas como FxCop. – LBushkin

+0

El público objetivo de .NET son las corporaciones estadounidenses (y, secundariamente, algunas pequeñas empresas). Si pudiera eludir la ofuscación de .NET, el software (caro de producir) podría volar fácilmente en las yemas de los dedos de la competencia. – micahhoover

Respuesta

31

respuesta básica:

Usted no puede con la API de reflexión (System.Reflection).

El motivo es que la API de reflexión está diseñada para trabajar con Metadatos (Tipo de clases, Nombre y Firma de métodos, ...) pero no en el nivel de datos (que sería la propia secuencia IL).

respuesta extendida:

Puede emitir (pero no leer) IL con System.Reflection.Emit (por ejemplo ILGenerator Class).

A través de MethodInfo.GetMethodBody() puede obtener el flujo de IL binario para la implementación de un método. Pero eso suele ser completamente inútil por sí mismo.

Hay bibliotecas externas (como Cecil) que puede usar para leer/modificar/agregar/eliminar código dentro de un método.

+1

¿No puede referirse al método a través de un delegado, luego crear un ExpressionTree del delegado e inspeccionar el árbol? –

+1

@Matt Greer: No. No se puede "aplicar ingeniería inversa" al cuerpo del método de un delegado en un árbol de expresiones. – LBushkin

+0

@Matt: Eso no te dará el código * dentro * del método, solo obtendrás 'MethodCallExpression' que te da acceso al mismo' MethodInfo' que podrías haber obtenido más directamente con la API de reflexión. – Aaronaught

1

No
Esta es una función programada para la próxima versión de C#. Puede usar CodeDom para obtener más información que reflexión, pero aún no puede interrogar al árbol de análisis.

Bueno, siempre hay mono, en mono el compilador es un servicio, y puede obtener los árboles de análisis en tiempo de ejecución.

La mejor pregunta es ¿por qué quieres?

1

Sí, debe haber una forma de lograr esto: la herramienta reflector .NET hace esto también. Sin embargo, no puedo decirte cómo se hace allí.

+1

¿Por qué no refleja el reflector;) – ntziolis

+9

Reflector no utiliza reflexión al menos no en el sentido de reflexión de .NET framework. En realidad, analiza el archivo PE y disimula el código IL de la sección .TEXT. Luego hace una coincidencia de patrones muy inteligente y genial para mapear/descompilar la IL de vuelta a un idioma de destino. –

2

Si no necesita hacer esto en tiempo real, eche un vistazo a Reflector. Puede desensamblar cualquier ensamblado .NET (incluidas las DLL principales de MS) y ver el código en el idioma de su elección. Esto puede ser muy educativo.

Actualización ¿Alguien ha intentado usar Reflector en reflector para descubrir cómo se hace esto?

+1

Tenga en cuenta que esto no optimiza el código. Entonces, si se hizo una optimización del compilador a la IL, no se devuelve a su fuente de compilación original, sino a una versión optimizada escrita menos humanamente.Es una buena manera de ver lo que podrías estar haciendo más eficientemente. – DevelopingChris

+0

No puede usar Reflector en Reflector. Pruébalo y verás, obtendrás una agradable sorpresa. – Aaronaught

+1

Reflector está encriptado de modo que no se puede reflejar en sí mismo, creo que utilizaron DotFuscator para hacerlo. – DevelopingChris

16

Eso depende de lo que signifique leer el código. Hay 4 formas del código.

1- El código fuente, por ejemplo. el original C# o VB.NET - No, no pueden conseguir esto con la reflexión
2- El código IL simbólica - No, no puede conseguir esto con la reflexión
3- El código ensamblador JITed - No, no puede conseguir esto con la reflexión

4- Los bytes de IL, los bytes reales a los que se compila IL, este puede obtener.

Eche un vistazo a MethodBase.GetMethodBody() por ejemplo, puede obtener los bytes de IL, las variables locales, los marcos de excepción, etc. http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody.aspx

+0

'GetMethodBody()' es lo más cercano que puede obtener, creo. – LBushkin

9

tipo de can. La función relevante es MethodBase.GetMethodBody.

No es exactamente la API más útil. Puede obtener información básica sobre lo que hay dentro del método, y puede obtener IL como una matriz de bytes. Eso es todo.

Hay un poco mejor API en la biblioteca Mono.Cecil, que expone una clase MethodDefinition con su propio MethodBody aplicación real que contiene Instructions, por lo que no tiene que interpretar el código de bytes en bruto. Aún así, si está buscando sacar el código C# a la Reflector, se sentirá profundamente decepcionado. Además, Cecil no está muy bien documentado.

Si aún quieres probar, entonces buena suerte.

Cuestiones relacionadas