Is it possible to insert IL code to C# method?
I just posted a utility which allows entire C# function bodies to be automatically replaced with inline IL, using a custom attribute. Like similar utilities, this works via the ILDASM/ILASM round-trip which can be set up as a post-build step. The tool also adjusts the PDB in order to preserve single-stepping and setting breakpoints on individual IL instructions in the debugger. It's different from some of the other round-trip IL inliners in that it (only) substitutes for entire function bodies, like this:
class MyClass
{
[ILFunc(@"
.locals init ([0] int32 i_arg)
ldc.i4.3
ret
")]
int MyFunc(int i_arg)
{
return 3;
}
};
For highly performance-critical methods, I tried using DynamicMethod
to improve upon compiler-generated IL, but found that the benefit is lost due to the delegate-calling overhead. Inline IL gives the the beneft of hand-tuned IL without that hit, assuming there are no runtime customizations that you would truly need DynamicMethod
for.
The complete source code is located at http://www.glennslayden.com/code/c-sharp/inline-il
Attribute
itself. –
Palisade DynamicMethod is the lightweight way to accomplish this at runtime.
The Microsoft C# compiler doesn't support injection of IL at compile-time, but a code-weaving tool could do so as a post-compile step.
I'll add my own tool to the list of solutions already provided here: InlineIL.Fody.
This uses the Fody assembly weaving tool to modify the assembly at build time. Which means all you have to do is install a NuGet package, add a config file to your project and you're done.
You're then provided with a simple and type-safe API to emit IL instructions, which you can mix with C# code. I believe it's easier to write IL in this way than writing text, and it's also more convenient than ILGenerator
since each opcode gets its own method with relevant overloads only.
Here's an example, with 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();
}
This shows how to access the initblk
instruction which C# doesn't currently expose.
If inline IL (in the same spirit of inline assembly supported by C and C++ compilers) is what you're looking for, this can be achieved using post-compilation round-trip compiling.
Mike Stall has once written a tool for that, as far as I know it's fairly mature:
Other than that, you could use F# which supports Inline IL.
The tool you need is called Cecil and is a part of the Mono project.
You can get more information about it here: http://www.mono-project.com/Cecil
Quoted from the website above:
Cecil is a library written by Jb Evain (http://evain.net/blog/) to generate and inspect programs and libraries in the ECMA CIL format. It has full support for generics, and support some debugging symbol format.
In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly.
© 2022 - 2024 — McMap. All rights reserved.