首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取在运行时使用TypeBuilder创建的类的类型

获取在运行时使用TypeBuilder创建的类的类型
EN

Stack Overflow用户
提问于 2017-01-07 00:45:02
回答 1查看 1.1K关注 0票数 1

在下面的代码块中,我正在使用SampleModel构建类( TypeBuilder )。一旦创建了该类型,我将尝试使用Type.GetType获取我刚刚创建的类的Type。但是Type.GetType正在返回null。为什么会这样呢?

代码语言:javascript
复制
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运行相同的程序时,我会间断性地得到类型。剩下的时间,我也会空的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-08 02:29:45

通过调用获取类型

代码语言:javascript
复制
assemblyBuilder.GetType (runtimeModelType.FullName)

调用Type.GetType依赖于融合来定位正确的程序集,我怀疑这个程序集可能不可靠,因为它是动态创建的。至少,它增加了一层不必要的复杂性。

LINQPad有一个额外的钩子来帮助运行时查找程序集,这可能是为了使它(有时)工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41516608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档