2017-01-07 3 views
1

Ich habe den folgenden Codeblock, in dem ich mit TypeBuilder eine Klasse (SampleModel) erstelle. Sobald der Typ erstellt wurde, versuche ich Type.GetType zu verwenden, um die Type der Klasse zu erhalten, die ich gerade erstellt habe. Aber Type.GetType gibt null zurück. Warum ist das?Abrufen des Typs einer Klasse, die zur Laufzeit mit TypeBuilder erstellt wurde

namespace TypeBuilderTest 
{ 
    using System; 
    using System.Reflection; 
    using System.Reflection.Emit; 

    class Program 
    { 
     static void Main() 
     { 
      // create a dynamic assembly and module 
      var assemblyName = new AssemblyName("SampleModelAssembly"); 
      var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 

      var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name); 

      var runtimeModelType = CreateRuntimeModel(moduleBuilder); 

      var type = Type.GetType(runtimeModelType.AssemblyQualifiedName); // <= This is the call in question. 
      Console.WriteLine("Type: " + type); 
     } 

     static private Type CreateRuntimeModel(ModuleBuilder moduleBuilder) 
     { 
      var modelName = "SampleModel"; 

      // create a new type builder 
      var typeBuilder = moduleBuilder.DefineType(
       modelName, 
       TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable); 

      AddProperty(typeBuilder, "SampleAttribute", typeof(string)); 

      return typeBuilder.CreateType(); 
     } 

     static public void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType) 
     { 
      // Generate a private field 
      FieldBuilder field = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); 

      // Generate a public property 
      // 
      // The last argument of DefineProperty is null, because the 
      // property has no parameters. (If you don't specify null, you must 
      // specify an array of Type objects. For a parameterless property, 
      // use the built-in array with no elements: Type.EmptyTypes) 
      PropertyBuilder property = 
       typeBuilder.DefineProperty(propertyName, 
           System.Reflection.PropertyAttributes.None, 
           propertyType, 
           null); 

      // The property set and property get methods require a special set of attributes: 
      MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; 

      // Define the "get" accessor method for current private field. 
      MethodBuilder currGetPropMthdBldr = 
       typeBuilder.DefineMethod("get_value", 
              GetSetAttr, 
              propertyType, 
              Type.EmptyTypes); 

      ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator(); 
      // For an instance property, argument zero is the instance. Load the 
      // instance, then load the private field and return, leaving the 
      // field value on the stack. 
      currGetIL.Emit(OpCodes.Ldarg_0); 
      currGetIL.Emit(OpCodes.Ldfld, field); 
      currGetIL.Emit(OpCodes.Ret); 

      // Define the "set" accessor method for current private field. 
      MethodBuilder currSetPropMthdBldr = 
       typeBuilder.DefineMethod("set_value", 
              GetSetAttr, 
              null, 
              new Type[] { propertyType }); 

      ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator(); 
      // Load the instance and then the numeric argument, then store the 
      // argument in the field. 
      currSetIL.Emit(OpCodes.Ldarg_0); 
      currSetIL.Emit(OpCodes.Ldarg_1); 
      currSetIL.Emit(OpCodes.Stfld, field); 
      currSetIL.Emit(OpCodes.Ret); 

      // Last, map the "get" and "set" accessor methods to the 
      // PropertyBuilder. The property is now complete. 
      property.SetGetMethod(currGetPropMthdBldr); 
      property.SetSetMethod(currSetPropMthdBldr); 
     } 
    } 
} 

runtimeModelType.AssemblyQualifiedName zeigt SampleModel, SampleModelAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

P. S: Wenn ich das gleiche Programm über LinqPad laufen, intermittierend ich die Art zurück. Die restliche Zeit werde ich auch dort null.

+0

Funktioniert es, wenn Sie assemblyBuilder.GetType (runtimeModelType.FullName) verwenden? –

+0

Super! Das hat funktioniert! Weißt du, warum der Type.GetType-Aufruf, den ich in LinqPad versuchte, zeitweise funktionierte? Wenn Sie Ihren Kommentar zu einer Antwort ändern können, kann ich sie auch akzeptieren. Vielen Dank! – pmohandas

+0

Weißt du auch, warum der Type.GetType-Aufruf überhaupt nicht funktioniert? – pmohandas

Antwort

2

Get nach Typ Typ

assemblyBuilder.GetType (runtimeModelType.FullName) 

Type.GetType Aufruf setzt auf Fusion Aufruf die korrekte Montage zu finden, die ich unzuverlässig sein vermuten könnte, weil es dynamisch erstellt wird. Zumindest fügt es eine Schicht unnötiger Komplexität hinzu.

LINQPad verfügt über einen zusätzlichen Hook, um die Laufzeitumgebung bei der Suche nach Assemblys zu unterstützen. Dies könnte dazu führen, dass es (manchmal) funktioniert.

Verwandte Themen