C#动态创建和动态使用程序集、类、方法、字段等

分类:技术交流

(3204)  (3)

  首先需要知道动态创建这些类型是使用的一些什么技术呢?其实只要相关动态加载程序集呀,类呀,都是使用反射,那么动态创建也一样使用的是反射,是属于反射的技术!也就是将对象或者数据映射成一个对象或者程序集保存起来而已。

  首先我们需要了解每个动态类型在.net中都是用什么类型来表示的。

程序集:System.Reflection.Emit.AssemblyBuilder(定义并表示动态程序集)

构造函数:System.Reflection.Emit.ConstructorBuilder(定义并表示动态类的构造函数)

自定义属性:System.Reflection.Emit.CustomAttributeBuilder(帮助生成自定义属性 使用构造函数传递的参数来生成类的属性)

枚举:System.Reflection.Emit.EnumBuilder(说明并表示枚举类型)

事件:System.Reflection.Emit.EventBuilder(定义类的事件)

字段:System.Reflection.Emit.FieldBuilder(定义并表示字段。无法继承此类)

局部变量:System.Reflection.Emit.LocalBuilder(表示方法或构造函数内的局部变量)

方法:System.Reflection.Emit.MethodBuilder(定义并表示动态类的方法(或构造函数))

模块:System.Reflection.Emit.ModuleBuilder(定义和表示动态程序集中的模块)

参数:System.Reflection.Emit.ParameterBuilder(创建或关联参数信息 如:方法参数,事件参数等)

属性:System.Reflection.Emit.PropertyBuilder(定义类型的属性 (Property))

类:System.Reflection.Emit.TypeBuilder(在运行时定义并创建类的新实例)

  我们有了这些类型,基本上就可以动态创建我们的任何需要使用的类型,当然很多可以动态创建的类型我不可能都介绍完,如果在项目中有需要可以去查阅MSDN,里面都有DEMO的,主要的问题就是要理解每一种类型的定义,比如:程序集加载是靠AppDomain,程序集里包含多个模块,模块里可以声明类,类里可以创建方法、属性、字段。方法需要在类中才可以创建的,局部变量是声明在方法体内等等规则。看MSDN就非常容易弄懂了。

1.如何动态创建它们了

AppDomain:应用程序域(由 AppDomain 对象表示)为执行托管代码提供隔离、卸载和安全边界。AppDomain同时可以载入多个程序集,共同来实现功能。

程序集:简单来说就是一个以公共语言运行库(CLR)为宿主的、版本化的、自描述的二进制文件。(说明:定义来自C#与.NET3.5高级程序设计(第四版))

模块:类似于以前的单元,用于分割不同的类和类型,以及资源(resource, 资源记录就是字符串,图象以及其它数据,他们只在需要的时候才会被调入内存)。类型的Meta信息也是模块的一部分。多个模块组建成一个程序集。

所谓动态就是在程序运行时,动态的创建和使用。

直接看代码吧,其实超级简单。

  1. //动态创建程序集
  2. AssemblyName DemoName = new AssemblyName("DynamicAssembly");
  3. AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);
  4. //动态创建模块
  5. ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll");
  6. //动态创建类MyClass
  7. TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
  8. //动态创建字段
  9. FieldBuilder fb = tb.DefineField("", typeof(System.String), FieldAttributes.Private);
  10. //动态创建构造函数
  11. Type[] clorType = new Type[] { typeof(System.String) };
  12. ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType);
  13. //生成指令
  14. ILGenerator ilg = cb1.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令
  15. ilg.Emit(OpCodes.Ldarg_0);
  16. ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
  17. ilg.Emit(OpCodes.Ldarg_0);
  18. ilg.Emit(OpCodes.Ldarg_1);
  19. ilg.Emit(OpCodes.Stfld, fb);
  20. ilg.Emit(OpCodes.Ret);
  21. //动态创建属性
  22. PropertyBuilder pb = tb.DefineProperty("MyProperty", PropertyAttributes.HasDefault, typeof(string), null);
  23. //动态创建方法
  24. MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
  25. MethodBuilder myMethod = tb.DefineMethod("get_Property", getSetAttr, typeof(string), Type.EmptyTypes);
  26. //生成指令
  27. ILGenerator numberGetIL = myMethod.GetILGenerator();
  28. numberGetIL.Emit(OpCodes.Ldarg_0);
  29. numberGetIL.Emit(OpCodes.Ldfld, fb);
  30. numberGetIL.Emit(OpCodes.Ret);
  31. //保存动态创建的程序集
  32. dynamicAssembly.Save(DemoName.Name + ".dll");

现在开始动态创建类:

构造函数:System.Reflection.ConstructorInfo(发现类构造函数的属性并提供对构造函数元数据的访问权)

事件:System.Reflection.EventInfo(发现事件的属性并提供对事件元数据的访问权)

字段:System.Reflection.FieldInfo(发现字段属性并提供对字段元数据的访问权)

方法:System.Reflection.MemberInfo(获取有关成员属性的信息并提供对成员元数据的访问)

成员:System.Reflection.MemberInfo(获取有关成员属性的信息并提供对成员元数据的访问)

参数:System.Reflection.ParameterInfo(发现参数属性并提供对参数元数据的访问)

属性:System.Reflection.PropertyInfo (发现属性 (Property) 的属性 (Attribute) 并提供对属性 (Property) 元数据的访问)

同样这是一种延伸阅读,只是先对这些进行了解,如果不知道的话,可能对动态的使用类型就无法下手了。

今天我做了一个Demo,先上Demo吧,然后在来解释程序是如何执行的。

  1. /动态创建的动态类型
  2. public static Type DynamicCreateType()
  3. {
  4. //动态创建程序集
  5. AssemblyName DemoName = new AssemblyName("DynamicAssembly");
  6. AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);
  7. //动态创建模块
  8. ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll");
  9. //动态创建类MyClass
  10. TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);
  11. //动态创建字段
  12. FieldBuilder fb = tb.DefineField("myField", typeof(System.String), FieldAttributes.Private);
  13. //动态创建构造函数
  14. Type[] clorType = new Type[] { typeof(System.String) };
  15. ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType);
  16. //生成指令
  17. ILGenerator ilg = cb1.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令
  18. ilg.Emit(OpCodes.Ldarg_0);
  19. ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
  20. ilg.Emit(OpCodes.Ldarg_0);
  21. ilg.Emit(OpCodes.Ldarg_1);
  22. ilg.Emit(OpCodes.Stfld, fb);
  23. ilg.Emit(OpCodes.Ret);
  24. //动态创建属性
  25. PropertyBuilder pb = tb.DefineProperty("MyProperty", PropertyAttributes.HasDefault, typeof(string), null);
  26. //动态创建方法
  27. MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
  28. MethodBuilder myMethod = tb.DefineMethod("get_Field", getSetAttr, typeof(string), Type.EmptyTypes);
  29. //生成指令
  30. ILGenerator numberGetIL = myMethod.GetILGenerator();
  31. numberGetIL.Emit(OpCodes.Ldarg_0);
  32. numberGetIL.Emit(OpCodes.Ldfld, fb);
  33. numberGetIL.Emit(OpCodes.Ret);
  34. //使用动态类创建类型
  35. Type classType = tb.CreateType();
  36. //保存动态创建的程序集 (程序集将保存在程序目录下调试时就在Debug下)
  37. dynamicAssembly.Save(DemoName.Name + ".dll");
  38. //创建类
  39. return classType;
  40. }

执行的主要方法

  1. static void Main(string[] args)
  2. {
  3. //动态创建的类类型
  4. Type classType = DynamicCreateType();
  5. //调用有参数的构造函数
  6. Type[] ciParamsTypes = new Type[] { typeof(string) };
  7. object[] ciParamsValues = new object[] { "Hello World" };
  8. ConstructorInfo ci = classType.GetConstructor(ciParamsTypes);
  9. object Vector = ci.Invoke(ciParamsValues);
  10. //调用方法
  11. object[] methedParams=new object[]{};
  12. Console.WriteLine(classType.InvokeMember("get_Field", BindingFlags.InvokeMethod, null, Vector, methedParams));
  13. Console.ReadKey();
  14. }

我创建了一个类,类里创建了有一个字段、有一个参数的构造函数、一个属性、有一个参数的构造函数和一个方法。用有参数的构造函数来初始化字段myField,然后调用get_Field方法返回myField字段的值。控制台程序显示“Hello World!!!”

C#动态创建和动态使用程序集、类、方法、字段等的更多相关文章

  1. js动态创建及移除div的方法

    本文实例讲述了js动态创建及移除div的方法.分享给大家供大家参考.具体实现方法如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  2. Fineui 根据datatable结构动态创建grid列,帮助类。动态绑定grid。

    public class FineuiHelper     {         /// <summary>         /// 动态创建Grid结构,在 Page_Init事件里执行( ...

  3. Delphi XE增强的RTTI妙用--动态创建包中的窗口类

    以前要在运行时创建package中的form类,必须要在form单元文件中这样注册类: Initialization  RegisterClass(TForm3);Finalization  UnRe ...

  4. 动态创建html元素的几种方法

    可以通过以下几种方式动态创建html元素: 1.使用jQuery创建元素的语法 2.把动态内容存放到数组中,再遍历数组动态创建html元素 3.使用模版   □ 使用jQuery动态创建元素追加到jQ ...

  5. OrmLite动态创建表,一个实体类创建多张表的的偏招

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/LonelyRoamer/article/details/26299355 在做一个Android的项 ...

  6. js中动态创建json,动态为json添加属性、属性值的实例

    如下所示: ? 1 2 3 4 5 6 7 var param = {};  for(var i=0;i<fields.length;i++){  var field = fields[i]; ...

  7. MFC之RTTI与动态创建

    本人能力.精力有限,所言所感都基于自身的实践和有限的阅读.查阅,如有错误,欢迎拍砖,敬请赐教——博客园:钱智慧. 在说RTTI之前需要明白c++中类静态成员的初始化特点:类的静态数据成员需要在类体外显 ...

  8. Qt Quick 组件和动态创建的对象具体的解释

    在<Qt Quick 事件处理之信号与槽>一文中介绍自己定义信号时,举了一个简单的样例.定义了一个颜色选择组件,当用户在组建内点击鼠标时,该组件会发出一个携带颜色值的信号,当时我使用 Co ...

  9. Android实现多页左右滑动效果,支持子view动态创建和cache

    要实现多页滑动效果,主要是需要处理onTouchEvent和onInterceptTouchEvent,要处理好touch事件的子控件和父控件的传递问题. 滚动控制可以利用android的Scroll ...

随机推荐

  1. git使用札记

    #1,本地推送到远程 查看本地关联的远程分支:git remote -v 添加远程分支:git remote add 推送本地到远程分支:git push URLOFYOURGIT #2,远程获取一个 ...

  2. 【跟着子迟品 underscore】JavaScript 数组展开以及重要的内部方法 flatten

    Why underscore (觉得这一段眼熟的童鞋可以直接跳到正文了...) 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. ...

  3. redis 学习 01(下载 学习资源)

    1. windows 版 redis 下载地址 https://github.com/MSOpenTech/redis/releases 2. redis 实战源码 http://redisinact ...

  4. php面向对象编程(一)

    类与对象关系: 类就像一个人类的群体 我们从类中实例化一个对象 就像是制定一个人. 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何来声明类, 做出来一个类很容易 ...

  5. js限制输入框只能输入数字

    分享下js限制输入框中只能输入数字的方法,包括整数与小数,分享几个例子,有需要的朋友参考下. 1.使用正则表达式限制输入框只能输入数字: <input type="text" ...

  6. EL表达式怎么获取Map的动态key?

    缘由 El表达式在调用Map的时候,后台传过来的Map的key不一定是一个固定的值,需要根据另外一个对象的id作为key来put,或者更加复杂的组合id+"string"作为一个k ...

  7. gulp错误GulpUglifyError: unable to minify JavaScript解决

    这个错误是由于在打包js代码时,js语法错误导致的,修改以下js的语法即可.

  8. 【Beta】第四次任务发布

    PM 日常管理&dev版宣传(周日开始). 后端 #99 服务发布 验收条件:使dev版能在www.buaaphylab.com下运行. 前端 #87 登录后能够查看与下载用户收藏的报告.生成 ...

  9. 【整理】认识MSG结构体

    在Windows程序中,消息是由MSG结构体来表示的.MSG结构体的定义如下(参见MSDN): typedef struct tagMSG { HWND hwnd; UINT message; WPA ...

  10. 非常提高mac生产力的一些插件归纳整理

    1.cheatsheet   快捷键提示插件,下载后按command键3秒,可以显示当前app的所有快捷键. 比如我现在在chrome的界面,按下command三秒,会弹出一个快捷键提示框. 2.Ba ...