C#笔记27: Emitting Dynamic Methods and Assemblies(动态程序集)
本文摘要:
1:什么是动态程序集
2:"Emitting Dynamic Methods and Assemblies”有什么用
3:动态程序集的一个简单例子
1:什么是动态程序集
程序集:简单来说就是一个以公共语言运行库(CLR)为宿主的、版本化的、自描述的二进制文件。
AppDomain:应用程序域(由 AppDomain 对象表示)为执行托管代码提供隔离、卸载和安全边界。AppDomain同时可以载入多个程序集,共同来实现功能。
动态程序集是指没有被编译至主程序,而是主程序在运行时动态调用或者生成的程序集。动态链接库(dll)大家一定很熟悉,它是一系列类和方法的打包,可以被不同的执行程序加载和共享,而C#生成的程序集也是dll。在实际应用中,一些程序不一定要在启动的时候就把所有dll文件都加载到内存中,而是根据需要动态加载或者创建。C#的反射和晚期绑定为实现这种操作提供了极大的帮助。
2:"Emitting Dynamic Methods and Assemblies”有什么用
System.Reflection.Emit 命名空间中的一组托管类型,它们允许编译器或工具在运行时发出元数据和 Microsoft 中间语言 (MSIL),或者也可以允许它们在磁盘上生成可迁移可执行 (PE) 文件。脚本引擎和编译器是此命名空间的主要用户。由 System.Reflection.Emit 命名空间提供的功能称为反射发出。
反射发出提供了以下功能:
-
使用 DynamicMethod 类在运行时定义轻量全局方法,然后使用委托执行这些方法。
-
在运行时定义程序集,然后运行这些程序集并/或将它们保存到磁盘。
-
在运行时定义程序集,运行这些程序集,然后将它们卸载,并允许垃圾回收来回收它们的资源。
-
在运行时定义新程序集中的模块,然后运行这些模块并/或将它们保存到磁盘。
-
在运行时定义模块中的类型,创建这些类型的实例,然后调用其方法。
-
为定义的模块定义可由调试器和代码分析器这样的工具使用的符号信息。
3:动态程序集的一个简单例子
//动态创建程序集 AssemblyName DemoName = new AssemblyName("DynamicAssembly"); AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave); //动态创建模块 ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + ".dll"); //动态创建类MyClass TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public); //动态创建字段 FieldBuilder fb = tb.DefineField("myField", typeof(System.String), FieldAttributes.Private); //动态创建构造函数 Type[] clorType = new Type[] { typeof(System.String) }; ConstructorBuilder cb1 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType); //生成指令 ILGenerator ilg = cb1.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令 ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Ldarg_1); ilg.Emit(OpCodes.Stfld, fb); ilg.Emit(OpCodes.Ret); //动态创建属性 PropertyBuilder pb = tb.DefineProperty("MyProperty", System.Reflection.PropertyAttributes.HasDefault, typeof(string), null); //动态创建方法 MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName; MethodBuilder myMethod = tb.DefineMethod("get_Field", getSetAttr, typeof(string), Type.EmptyTypes); //生成指令 ILGenerator numberGetIL = myMethod.GetILGenerator(); numberGetIL.Emit(OpCodes.Ldarg_0); numberGetIL.Emit(OpCodes.Ldfld, fb); numberGetIL.Emit(OpCodes.Ret); //使用动态类创建类型 Type classType = tb.CreateType(); //保存动态创建的程序集 (程序集将保存在程序目录下调试时就在Debug下) dynamicAssembly.Save(DemoName.Name + ".dll");
4:更多资料
本章不打算仔细阐述动态程序集,更多内容在:
MSDN:http://msdn.microsoft.com/zh-cn/library/8ffc3x75.aspx
OTHER:http://www.cnblogs.com/allenlooplee/archive/2007/06/24/794116.html
练习:
1.You need to create a dynamic assembly named MyAssembly. You also need to save the assembly to disk.
Which code segment should you use?
A. AssemblyName myAssemblyName = new AssemblyName();
myAssemblyName.Name = "MyAssembly";
AssemblyBuilder myAssemblyBuilder =AppDomain.CurrentDomain.DefineDynamicAssembly
(myAssemblyName, AssemblyBuilderAccess.Run);
myAssemblyBuilder.Save("MyAssembly.dll");
B. AssemblyName myAssemblyName = new Assemb lyName();myAssemblyName.Name = "MyAssembly";
AssemblyBuilder myAssemblyBuilder =AppDomain.CurrentDomain.DefineDynamicAssembly
(myAssemblyName, AssemblyBuilderAccess.Save);
myAssemblyBuilder.Save("MyAssembly.dll");
C. AssemblyName myAssemblyName =new AssemblyName();
AssemblyBuilder myAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly
(myAssemblyName, AssemblyBuilderAccess.RunAndSave);
myAssemblyBuilder.Save("MyAssembly.dll");
D. AssemblyName myAssemblyName =new AssemblyName("MyAssembly");
AssemblyBuilder myAssemblyBuilder =AppDomain.CurrentDomain.DefineDynamicAssembly
(myAssemblyName, AssemblyBuilderAccess.Save);
myAssemblyBuilder.Save("C. \\MyAssembly.dll");
Answer: B