获取已关闭的未创建泛型方法的令牌

本文关键字:创建 泛型方法 令牌 获取 | 更新日期: 2023-09-27 18:34:40

我正在使用MethodBuilder.SetMethodBody()来发出该方法,而不是使用内置的ILGenerator。原因主要是对异常处理信息进行更多控制,并且通常对发出的操作码有更多的控制。

在我需要对我正在调用的方法发出调用的所有情况下ModuleBuilder.GetMethodToken()它工作正常,除非我需要call未创建的封闭泛型方法(具有相同的动态模块(。它抛出了一个NotSupportedException:Specified method is not supported..

当然MethodBuilder.TokenMetadata不起作用,因为该方法是未创建的,这使我无所事

事。

所以问题是,如何让令牌用于向此泛型方法自定义发射call操作码?

编辑:我发现内置ILGenerator.EmitCall通过调用接受布尔值的内部方法来获取令牌,生成器有时会传递 false。但是,MethodBuilder.GetMethodToken()始终传递给相同的内部方法。好像是这样,但既然内部方法超出了我的能力范围,那么还得有另一种方法吗?

如果没有其他方法,我实际上正在考虑使用反射来手动获取和调用该方法。

编辑:事实上,通过反射调用内部方法(顺便说一句,ModuleBuilder.GetMethodTokenInternal顺便说一下(以 false 作为参数确实解决了这个问题。但我不相信没有正常的方式来获取令牌,因为如果您手动调用泛型方法,SetMethodBody需要它。

获取已关闭的未创建泛型方法的令牌

我想出的解决方案是通过反射调用内部方法并向其传递所需的参数。

// If the to be called method is generic...
var methodInfo = Type.GetType("System.Reflection.Emit.ModuleBuilder")
                    .GetTypeInfo()
                    .DeclaredMethods
                    .Where((method) => method.Name == "GetMethodTokenInternal" && method.GetParameters().Length == 3)
                    .First();
int token = 
    (int)methodInfo.Invoke(_moduleBuilder, new object[] { closedGenericMethod, null, false });

但我实际上使用委托在第一次调用后使事情变得更快。