c# - 如何在 IL 中调用同一类中的方法
问题描述
如果我正在编写代码,这将非常简单。我的代码如下所示:
public class SomeClass
{
public void SomeMethod(ISomeService someService)
{
}
private void AnotherMethod(ISomeService someService)
{
}
}
我可以使用 Type 引用获取这两种方法的 Method 定义,但我想要的是从 SomeMethod 到在 IL 中添加的 AnotherMethod 的调用,因此您将拥有类似的等效代码:
public void SomeMethod(ISomeService someService)
{
AnotherMethod(someService);
}
我现在完全迷失了,试图理解如何正确构建必要的指令。
我现在拥有的看起来像:
private void ProcessType(TypeDefinition typeDef)
{
var anotherMethodDef = typeDef.Methods.FirstOrDefault(x => HasMethod(x, "AnotherMethod"));
if(someMethodDef != null)
{
var someMethodDef = typeDef.Methods.First(x => HasMethod(x, "SomeMethod"));
var processor = someMethodDef.Body.GetILProcessor();
// Now I need to generate:
// AnotherMethod(someService); as a new instruction
}
}
private static bool HasMethod(MethodDefinition method, string expected) =>
method.Name == expected && method.Parameters.Count() == 1 &&
method.Parameters.First().TypeDefinition.FullName == "Contoso.ISomeService";
解决方案
不确定这是否有帮助,但 IL SomeMethod
:
.maxstack 8
IL_0000: nop
IL_0001: ret
和 IL 的SomeMethod
withAnotherMethod(someService);
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: call instance void SomeClass::AnotherMethod(class [YourAssembly]YourNamespace.ISomeService)
IL_0008: nop
IL_0009: ret
所以你想在中间添加这个:
// Add breakpoint space (https://stackoverflow.com/questions/4590382/why-does-generated-il-code-start-with-a-nop)
IL_0000: nop
// Load `this` (https://stackoverflow.com/questions/1785372/why-do-i-have-to-do-ldarg-0-before-calling-a-field-in-msil)
IL_0001: ldarg.0
// Load your first argument... which is `someService`
IL_0002: ldarg.1
// Call method with this signature and previously loaded arguments
IL_0003: call instance void SomeClass::AnotherMethod(class [YourAssembly]YourNamespace.ISomeService)
最后这应该可以解决问题:
var myAssembly = Assembly.GetAssembly(typeof(SomeClass));
var module = myAssembly.MainModule;
var anotherMethodRef = module.Import(typeof(SomeClass).GetMethod("AnotherMethod", new[] { typeof(ISomeService) }));
var nop = processor.Create(OpCodes.Nop);
var loadThis = processor.Create(OpCodes.Ldarg_0);
var loadSomeService = processor.Create(OpCodes.Ldarg_1);
var callMethod = processor.Create(OpCodes.Call, anotherMethodRef);
// First instruction was IL_0000: nop
var firstInstruction = someMethodDef.Body.Instructions[0];
processor.InsertBefore(firstInstruction, nop);
processor.InsertBefore(firstInstruction, loadThis);
processor.InsertBefore(firstInstruction, loadSomeService);
processor.InsertBefore(firstInstruction, callMethod);
推荐阅读
- django - 整合条纹 - JSONDecodeError
- ubuntu - ubuntu 上的 Lua 出现 nginx 错误:找不到模块“加密”
- python - Python sum() 在以不同方式排序的同一列表上给出舍入错误
- python - sns matplotlib 输出切片保存的图像
- postgresql - Postgresql 计算嵌套 json 中值的出现次数
- python - 如何通过实时流输入到 pandas 数据框?
- spring - 在 Spring Boot Cloud Kubernetes 本地测试中调用 listNamespacedConfigMap(Async) 时缺少必需的参数“命名空间”
- javascript - 从对象数组中删除对象的问题
- sql - DB2 存储过程 IF/ELSE —— 我缺少什么?
- caching - 如何知道资源是否真正从 chrome devtools 的缓存中加载?