如何用MonoCecil生成对应Current属性的IL指令,使反编译显示为属性访问?
Enumerator.Current Property Access with MonoCecil I get exactly what you're dealing with here—trying to replicate that clean enumerator.Current property access in decompiled C# instead of having it show up as a raw get_Current() method call. The key mistake here is directly creating a MethodReference for get_Current; you need to work with MonoCecil's property metadata handling instead.
Why Your Initial Approach Fails
Even though property access in IL does boil down to calling the get_XXX method, decompilers rely on the property metadata to recognize it as a property access rather than a regular method call. When you manually create a MethodReference for get_Current, you're skipping that metadata link, so decompilers can't map it back to the Current property.
The Fix: Use Property References
Here's how to properly generate the IL that will decompile to enumerator.Current:
- Get the type reference for
List<int>.Enumerator - Retrieve the
Currentproperty from that type - Use the property's built-in
GetMethodto get the correctMethodReference - Generate the IL instruction using that method reference
Here’s a concrete code example tailored to your TestClass.Sum() scenario:
// Assume you already have your ModuleDefinition and target MethodDefinition (Sum) ModuleDefinition module = ...; // Your module reference MethodDefinition sumMethod = ...; // The Sum method you're modifying // Import the List<int>.Enumerator type into your module TypeReference listEnumeratorType = module.ImportReference(typeof(List<int>.Enumerator)); // Find the Current property on the enumerator type PropertyDefinition currentProperty = listEnumeratorType.Properties.First(p => p.Name == "Current"); // Get the get_Current method reference from the property (this carries property metadata) MethodReference getCurrentMethod = currentProperty.GetMethod; // Generate the IL instruction to call the get method sumMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Call, getCurrentMethod));
Key Notes
- Use
ImportReferencefor generic types: This ensures MonoCecil correctly handles the generic type arguments forList<int>.Enumerator. - Call vs. Callvirt: Since
List<T>.Enumeratoris a value type, you'll useOpCodes.Callinstead ofOpCodes.Callvirthere (which matches the decompiled IL you shared). If you were working with a reference type enumerator, you might useCallvirtinstead. - Metadata Matters: By going through the
PropertyDefinition, you're preserving the link between the method call and the property metadata. Decompilers like ILSpy or dnSpy will pick up on this and displayenumerator.Currentinstead of the raw method call.
This approach will generate IL that matches what you see in your decompiled example, and the resulting code will decompile cleanly to the property access you want.
内容的提问来源于stack exchange,提问作者M.Y. Babt

