动态创建类

来源:互联网 发布:unity3d文件解包 编辑:程序博客网 时间:2024/06/10 10:54

  // 创建新类,集成自 object

  TypeBuilder typebuilder = GetTypeBuilder(Math.Abs("CT3".GetHashCode()), typeof(object));

  // 为新类增加属性 A, B, C
  CreateProperty(typebuilder, "A", typeof(string));
  CreateProperty(typebuilder, "B", typeof(int));
  CreateProperty(typebuilder, "C", typeof(DateTime));

 

  // t 就是新创建出的类的 Type
  Type t = typebuilder.CreateType();

 

  // 创建这个类的实例
  var st = Activator.CreateInstance(t);

 

 

* http://www.myext.cn/csharp/5739.html

* http://www.cnprog.com/questions/58/  c#里怎样给一个类动态增加属性?

* http://www.silverlightchina.net/html/tips/2010/1020/2763.html

 

  // 下面是创建类的方法 和 为类增加属性的方法(转自别人的代码)

 

 

       //创建动态 类型 及包含它的动态 Assembly
        private static TypeBuilder GetTypeBuilder(int iHashCode, Type baseClass)
        {
            //动态创建Assembly,名称为 "TempAssembly" 加 IEnumerable<IDictionary>实例的 Hash         //Code 字符串
            //原因:同时多用户操作,同时创建多个动态 Assembly,这种命名可唯一标识每个
            AssemblyName an = new AssemblyName("TempAssembly" + iHashCode);
            //当前应用程序的当前 Domain 创建动态 Assembly ,并指定运行时可用
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                an, AssemblyBuilderAccess.Run);

            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");

            TypeBuilder tb = moduleBuilder.DefineType(
                string.Format("TempType{0}", iHashCode), //类型命名与 Assembly 一致。类型名称在                                               //一个程序集内必须是唯一的。
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                baseClass);//指定创建类型的基类

            //定义类型的缺省构造函数
            ConstructorBuilder constructor = tb.DefineDefaultConstructor(
                MethodAttributes.Public |
                MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName);


            return tb;
        }

        //类型的属性成员由两部分组成,一是私有字段,二是访问私有字段的属性包装器。
        //包装器运行时的本质与 Method 一样,即包含 Set_Method 和 Get_Method 两个方法。
        private static void CreateProperty(TypeBuilder typeBuilder, string propertyName,
            Type propertyType)
        {
            //TypeBuilder 的 DefineField()、DefineProperty()、DefineMethod() 方法分别在类中定义及添    //加 字段、属性、方法,并返回相应的实例引用        
            FieldBuilder fieldBuilder = typeBuilder.DefineField(
               string.Format("_{0}", propertyName),//字段名称常用命名规则:下划线( _ ) + 属性名
                 propertyType,
                 FieldAttributes.Private); //属性字段定义为私有

            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName,
                PropertyAttributes.HasDefault,  //有缺省值
                  propertyType,                   //返回类型为属性类型
                  null);                          //没有参数类型

            //Set_Method
            MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod(
                //getter 属性在IL代码中转换为 get_<PropertyName>() 方法, 命名方式要保持一致
                 string.Format("get_{0}", propertyName),
                 MethodAttributes.Public |
                 MethodAttributes.SpecialName | //指示此方法是特殊的。名称描述此方法的特殊性(get_)。
                 MethodAttributes.HideBySig,    //指示此方法按名称和签名隐藏
                 propertyType, Type.EmptyTypes);//只有返回类型,没有参数类型

            //获取对象的MSIL流
            ILGenerator getIL = getPropMthdBldr.GetILGenerator();
            getIL.Emit(OpCodes.Ldarg_0);            //向MSIL流发送属性实例
            getIL.Emit(OpCodes.Ldfld, fieldBuilder);//装载属性私有字段
            getIL.Emit(OpCodes.Ret);                //堆栈中保留发出的值并返回

            //Get_Method
            MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod(
                //setter 属性在IL代码中转换为 set_<PropertyName>() 方法, 命名方式要保持一致
                 string.Format("set_{0}", propertyName),
                 MethodAttributes.Public |
                 MethodAttributes.SpecialName |
                 MethodAttributes.HideBySig,
                 null, new Type[] { propertyType });//没有返回类型,有参数类型

            ILGenerator setIL = setPropMthdBldr.GetILGenerator();
            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldarg_1);            //装载需要设置的属性值
            setIL.Emit(OpCodes.Stfld, fieldBuilder);//设置属性字段值,即保存传入的参数值
            setIL.Emit(OpCodes.Ret);

            //属性包装器与相应的 Set_Method 和 Get_Method 建立关联,生成完整的属性定义
            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }