Get the sign of a private uncreated general method

I use MethodBuilder.SetMethodBody()to emit a method instead of using the built-in ILGenerator. The reason is that basically there is more control with information about handling exceptions and, as a rule, for more control over outgoing opcodes.

In all situations when I need to call a method call that I call ModuleBuilder.GetMethodToken(), and it works fine, except when I need a callclosed generalized method that has not been created (with the same dynamic module), It throws NotSupportedException:Specified method is not supported..

Of course, it MethodBuilder.TokenMetadatadoes not work, because the method has not been created, and it does not give me anything else to try.

So the question is, how do I get a token for use in my user emitting opcode callfor this general method?

Edit: I found out that the built-in ILGenerator.EmitCallreceives the token through a call to the internal method that the bool accepts, the generator sometimes passes false. However, it MethodBuilder.GetMethodToken()always passes true to the same internal method. This seems to be true, but since internal methods are not available, should there be another way?

I really think about using reflection to get and call a method manually if there is no other way.

Edit: Indeed, calling the internal method (which is ModuleBuilder.GetMethodTokenInternalbtw) through reflection with false, as the parameter really solves the problem. But I don’t think that the normal way to get a token is because it SetMethodBodyneeds it if you manually call the general method.

+4
source share
1 answer

The solution I came up with invokes the internal method through reflection and passes the necessary arguments to it.

// 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 });

But I really use a delegate to speed things up after the first call.

+1
source

Source: https://habr.com/ru/post/1568320/


All Articles