The problem
I'm trying to get this IL instruction using strictly Mono.Cecil
. Right now, the only solution I found involves importing every references assembly and their exported types, call MakeGenericInstanceType()
, and Module.Import()
.
Wanted IL instruction
The code it produces is:
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>)
What I can get (using only references)
I'm trying to do the same thing without importing everything (hence using only references), but can't do it. The two closest things I've done (and don't work) are:
Test 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>)
Problem: !!0
is replaced by !1
.
Test 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>>)
Problem: all generics explicitly defined:
!0
=>string
!!0
=>class MyClass`1<valuetype [mscorlib]System.DateTime>
The question
Any idea how to get the wanted instruction, using only references?
The successful (but very hack-y) code
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()
imports every Assembly, loads it in memory, and enumerates its types.
The non-successful code (Test 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);
Any idea?