mardi 12 janvier 2016

TypeLoadException while creating type via TypeBuilder in C#

I am having trouble with understeanding exception thrown by CreateType method. Exception and second question are at the end.

Code looks as follows :

Definitions (works - I hope) :

AssemblyName name = new AssemblyName("MyOwnNewAssembly"); 
AssemblyBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = builder.DefineDynamicModule("Emission", "Emission.dll"); 
TypeBuilder typeBuilder = moduleBuilder.DefineType("User", TypeAttributes.Public);
typeBuilder.SetParent(typeof(object)); 
var field = typeBuilder.DefineField("name", typeof(string), FieldAttributes.Private);

Constructor creation (works):

var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Any, new Type[] { typeof(String) });
var baseConstructor = typeof(object).GetConstructor(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, new Type[0], null);var genertaor = constructor.GetILGenerator();
genertaor.Emit(OpCodes.Ldarg_0);         
genertaor.Emit(OpCodes.Call, baseConstructor);  
genertaor.Emit(OpCodes.Nop);
genertaor.Emit(OpCodes.Nop);
genertaor.Emit(OpCodes.Ldarg_0);  
genertaor.Emit(OpCodes.Ldarg_1);  
genertaor.Emit(OpCodes.Stfld, field);  
genertaor.Emit(OpCodes.Ret);

And now here is code which doesn't work - overriding ToString:

var method = typeof(object).GetMethod("ToString");
var toStringBuilder = typeBuilder.DefineMethod("ToString", MethodAttributes.Public, null, Type.EmptyTypes);
typeBuilder.DefineMethodOverride(toStringBuilder, method);
var generator2 = toStringBuilder.GetILGenerator();
generator2.Emit(OpCodes.Nop);
generator2.Emit(OpCodes.Ldarg_0); 
generator2.Emit(OpCodes.Ldfld, field);
generator2.Emit(OpCodes.Stloc_0);
generator2.Emit(OpCodes.Ldloc_0);
generator2.Emit(OpCodes.Ret,field);

and creating type (works):

typeBuilder.CreateType();
builder.Save("Emission.dll");

Here is code wich I am trying to create :

public class User{
   private string _name;
   public User(string name){
      _name = name;
   }
   public override string ToString(){
      return _name;
   }
}

After decompilation above ToString looks like :

.method public hidebysig virtual 
instance string ToString () cil managed 
{
.maxstack 1
.locals init (
[0] string
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld string AssemblyBuilding.User::_name
IL_0007: stloc.0
IL_0008: br.s IL_000a

IL_000a: ldloc.0
IL_000b: ret
} // end of method User::ToString

And my other question is why

    IL_0007: stloc.0
    IL_0008: br.s IL_000a

    IL_000a: ldloc.0

doesn't looks like this (why there is a jump) :

IL_0007: stloc.0
IL_000a: ldloc.0

Exception is :

An unhandled exception of type 'System.TypeLoadException' occurred in mscorlib.dll

Additional information: Signature of the body and declaration in a method implementation do not match. Typ: 'User'. Assembly: 'MyOwnNewAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.





Aucun commentaire:

Enregistrer un commentaire