2017-01-07 6 views
1

У меня есть следующий блок кода, где я создаю класс (SampleModel) с помощью TypeBuilder. Как только тип был создан, я пытаюсь использовать Type.GetType, чтобы получить Type класса, который я только что создал. Но Type.GetType возвращается null. Почему это?Получение типа класса, созданного во время выполнения с использованием TypeBuilder

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 показывает SampleModel, SampleModelAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

P.S: Когда я запускаю ту же программу с помощью LINQPad, периодически я получаю тип обратно. В остальное время я тоже получаю нуль.

+0

Это работает, если вы используете assemblyBuilder.GetType (runtimeModelType.FullName)? –

+0

Удивительный! Это сработало! Вы знаете, почему вызов Type.GetType, который я пытался в LinqPad, работал с перерывами? Кроме того, если вы могли бы сменить свой комментарий на ответ, я могу его принять. Благодаря! – pmohandas

+0

Кроме того, вы знаете, почему вызов Type.GetType не будет работать в первую очередь? – pmohandas

ответ

2

Получить Тип по телефону

assemblyBuilder.GetType (runtimeModelType.FullName) 

Вызов Type.GetType опирается на слияние, чтобы найти правильную сборку, которую я подозреваю, может быть ненадежным, потому что он создается динамически. Как минимум, он добавляет слой ненужной сложности.

LINQPad имеет дополнительный крючок, чтобы помочь сборщикам времени выполнения, и это может привести к его (иногда) работе.