问题
我正在尝试使用严格的 Mono.Cecil
获取此 IL 指令。目前,我找到的唯一解决方案涉及导入每个引用程序集及其导出类型,调用 MakeGenericInstanceType()
和 Module.Import()
。
所需的 IL 指令
它生成的代码如下:
call instance class [mscorlib]System.Threading.Tasks.Task`1<!!0> class [mscorlib]System.Threading.Tasks.Task`1<string>::ContinueWith<class MyClass`1<valuetype [mscorlib]System.DateTime>>(class [mscorlib]System.Func`2<class [mscorlib]System.Threading.Tasks.Task`1<!0>, !!0>)
我可以通过引用获得什么
我想尝试不导入全部内容来完成同样的事情(因此只使用引用),但是做不到。我尝试了两个最接近的方法(也不起作用):
测试1
call instance class [mscorlib]System.Threading.Tasks.Task`1<!1> class [mscorlib]System.Threading.Tasks.Task`1<string>::ContinueWith<class MyClass`1<valuetype [mscorlib]System.DateTime>>(class [mscorlib]System.Func`2<class [mscorlib]System.Threading.Tasks.Task`1<!0>, !1>)
问题: !!0
被替换为 !1
。
测试2
call instance class [mscorlib]System.Threading.Tasks.Task`1<class MyClass`1<valuetype [mscorlib]System.DateTime>> class [mscorlib]System.Threading.Tasks.Task`1<string>::ContinueWith<class MyClass`1<valuetype [mscorlib]System.DateTime>>(class [mscorlib]System.Func`2<class [mscorlib]System.Threading.Tasks.Task`1<string>, class MyClass`1<valuetype [mscorlib]System.DateTime>>)
问题:所有泛型都是显式定义的:
!0
=>string
!!0
=>class MyClass`1<valuetype [mscorlib]System.DateTime>
问题
有什么办法只使用引用就能得到所需的指令吗?
成功(但非常hack-y)的代码
var task = module.GetEverySingleType().First(...);
var returnType = module.GetEverySingleType().First(...);
var continueWith = module.Import((from m in task.GetMethods()
where m.Name == "ContinueWith"
let p = m.GetParameters()
where p.Length == 1 && p[0].ParameterType.Name == "Func`2"
select m.MakeGenericMethod(returnType)).First());
Instruction.Create(OpCodes.Call, continueWith);
GetEverySingleType()
导入每个程序集,将其加载到内存中,并枚举其类型。
不成功的代码(测试2)
var func = Module.Import(typeof(Func<,>)).MakeGenericType(taskType, returnType);
var continueWith = new GenericInstanceMethod(new MethodReference("ContinueWith", Module.Import(typeof(Task<>)).MakeGenericInstanceType(returnType), taskType) { HasThis = true });
continueWith.GenericArguments.Add(returnType);
continueWith.Parameters.Add(new ParameterDefinition(Module.Import(typeof(Func<,>)).MakeGenericType(taskType, returnType)));
Instruction.Create(OpCodes.Call, continueWith);
有什么想法吗?