gpt4 book ai didi

c# - 试图从 Mono.Cecil 引用 Task.ContinueWith

转载 作者:行者123 更新时间:2023-11-30 18:19:56 25 4
gpt4 key购买 nike

问题

我正在尝试严格使用 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);

有什么想法吗?

最佳答案

在第二个示例中,continueWith 中没有任何通用参数,这就是生成的方法引用不使用任何参数的原因。您针对的方法签名使用两个,!0!!0。您必须保留通用参数,并且返回/参数类型必须使用它们。从系统程序集导入东西似乎没有问题,所以试试这个:

var bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly ;

// import the *generic method* from the *generic type*
// can be done once per module
var cwgg = module.Import (typeof (Task<>).GetMethods (bf).Where (_ =>
_.Name == "ContinueWith" &&
_.IsGenericMethodDefinition &&
_.GetParameters ().Length == 1).Single ()) ;

// close Task<>, keep ContinueWith generic parameter open
var cwgi = new MethodReference (cwgg.Name, cwgg.ReturnType, taskType) ;
cwgi.HasThis = true ;
cwgi.GenericParameters.Add (new GenericParameter ("TNewResult", cwgi)) ;
cwgi.Parameters.Add (new ParameterDefinition (
cwgg.Parameters[0].ParameterType)) ;

// close ContinueWith
var continueWith = new GenericInstanceMethod (cwgi) ;
continueWith.GenericArguments.Add (returnType) ;

关于c# - 试图从 Mono.Cecil 引用 Task.ContinueWith<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38061395/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com