Partilhar via


Token APIs on Module Builder

We have some token APIs on Module Builder that can be used to as an optional approach as to regular Refelction.Emit APIs.

They are:

public TypeToken GetTypeToken(Type type)

public TypeToken GetTypeToken(String name) // this looks just like ModuleBuilder.GetType(string).

public MethodToken GetMethodToken(MethodInfo method)

public MethodToken GetArrayMethodToken(Type arrayClass, String methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)

public MethodToken GetConstructorToken(ConstructorInfo con)

public FieldToken GetFieldToken(FieldInfo field)

public StringToken GetStringConstant(String str)

public SignatureToken GetSignatureToken(SignatureHelper sigHelper)

public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)

Here is a code sample showing you the useage as GetArrayMethod for referenced Generic Methods:

using System.Reflection;
using System.Reflection.Emit;
using System;

public class Test
{
public static void Main()
{
AssemblyBuilder asmb = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("C"), AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modb = asmb.DefineDynamicModule("C.dll");
TypeBuilder A = modb.DefineType("A", TypeAttributes.Public);
MethodBuilder AM = A.DefineMethod("M", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[]{});
ILGenerator ilgen = AM.GetILGenerator();
MethodToken mtToken = modb.GetMethodToken(typeof(G<int>).GetMethod("Foo"));
LocalBuilder loc = ilgen.DeclareLocal(typeof(G<int>));
ilgen.Emit(OpCodes.Ldnull);
ilgen.Emit(OpCodes.Call, mtToken.Token);
ilgen.Emit(OpCodes.Ldc_I4, 0);
ilgen.Emit(OpCodes.Ret);
A.CreateType();
asmb.Save("C.dll");
}
}
public class G<T>
{

    public static void Foo(G<T> foo)
{
}
}

The code we emitted look like this:

.method public static int32  M() cil managed
{
  // Code size       12 (0xc)
  .maxstack  2
  .locals init (class [repro]G`1<int32> V_0)
  IL_0000:  ldnull
  IL_0001:  call       void class [repro]G`1<int32>::Foo(class [repro]G`1<!0>)
  IL_0006:  ldc.i4     0x0
  IL_000b:  ret
} // end of method A::M

Due to some bugs in Reflection in Beta2, a similiar emitting using normal TypeBuilder.GetMethod won't work in this case. But by using the token APIs, we work directly on module builders and don't need to go through Reflection and thus can correctly emit the signature. It could be also memeory saving for you as well if you just cache the token instead of caching the method info during emitting, you can probably make your GC heap smaller.