tag - Cómo insertar código CIL en C#
summary c# visual studio (5)
¿Es posible insertar el código IL en el método C #?
Acabo de publicar una utilidad que permite que todos los cuerpos de funciones de C # se reemplacen automáticamente con el IL en línea, usando un atributo personalizado. Al igual que las utilidades similares, esto funciona a través del viaje de ida y vuelta de ILDASM / ILASM que se puede configurar como un paso posterior a la construcción. La herramienta también ajusta el PDB para preservar el paso a paso y establecer puntos de interrupción en instrucciones IL individuales en el depurador. Es diferente de algunos de los otros inliners de IL de ida y vuelta en que (solo) sustituye a cuerpos de funciones completos, como este:
class MyClass
{
[ILFunc(@"
.locals init ([0] int32 i_arg)
ldc.i4.3
ret
")]
int MyFunc(int i_arg)
{
return 3;
}
};
Para métodos altamente críticos para el rendimiento, traté de usar DynamicMethod
para mejorar el IL generado por el compilador, pero descubrí que el beneficio se pierde debido a la sobrecarga de llamadas de delegado. Inline IL ofrece el beneficio de IL sintonizado a mano sin ese impacto, asumiendo que no hay personalizaciones de tiempo de ejecución para las que realmente necesitaría DynamicMethod
.
El código fuente completo se encuentra en http://www.glennslayden.com/code/c-sharp/inline-il
Agregaré mi propia herramienta a la lista de soluciones ya proporcionada aquí: InlineIL.Fody .
Esto utiliza la herramienta de tejido de ensamblaje Fody para modificar el ensamblaje en el momento de la construcción. Lo que significa que todo lo que tiene que hacer es instalar un paquete NuGet, agregar un archivo de configuración a su proyecto y listo.
Luego se le proporciona una API simple y segura para el tipo para emitir instrucciones IL, que puede combinar con el código C #. Creo que es más fácil escribir IL de esta manera que escribir texto, y también es más conveniente que ILGenerator
ya que cada código de operación obtiene su propio método solo con sobrecargas relevantes.
Aquí hay un ejemplo, con el using static InlineIL.IL.Emit;
:
public static void ZeroInit<T>(ref T value)
where T : struct
{
Ldarg(nameof(value));
Ldc_I4_0();
Sizeof(typeof(T));
Unaligned(1);
Initblk();
}
Esto muestra cómo acceder a la instrucción initblk
que C # no expone actualmente.
La herramienta que necesita se llama Cecil y es parte del proyecto Mono.
Puede obtener más información al respecto aquí: http://www.mono-project.com/Cecil
Citado desde el sitio web anterior:
Cecil es una biblioteca escrita por Jb Evain ( http://evain.net/blog/ ) para generar e inspeccionar programas y bibliotecas en el formato ECMA CIL. Tiene soporte completo para genéricos y admite algunos formatos de símbolos de depuración.
En inglés simple, con Cecil, puede cargar ensamblajes administrados existentes, explorar todos los tipos contenidos, modificarlos sobre la marcha y guardar en el disco el ensamblaje modificado.
Si lo que está buscando es Inline (en el mismo espíritu de ensamblaje en línea soportado por compiladores C y C ++), esto se puede lograr utilizando la compilación de ida y vuelta posterior a la compilación.
Mike Stall una vez ha escrito una herramienta para eso , que yo sepa que es bastante madura:
Aparte de eso, puedes usar F # que admite Inline IL.
DynamicMethod es la forma liviana de lograr esto en tiempo de ejecución.
El compilador de Microsoft C # no admite la inyección de IL en tiempo de compilación, pero una herramienta de tejido de código podría hacerlo como un paso posterior a la compilación.