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

1 篇文章 0 订阅
1 篇文章 0 订阅

    

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

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

  首先我们需要了解每个动态类型在.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信息也是模块的一部分。多个模块组建成一个程序集。

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

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

  

[csharp] view plain copy print ?
  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");  
<span style="font-size:14px;">//动态创建程序集
            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("", 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", PropertyAttributes.HasDefault, typeof(string), null);
            //动态创建方法
            MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
            MethodBuilder myMethod = tb.DefineMethod("get_Property", getSetAttr, typeof(string), Type.EmptyTypes);
            //生成指令
            ILGenerator numberGetIL = myMethod.GetILGenerator();
            numberGetIL.Emit(OpCodes.Ldarg_0);
            numberGetIL.Emit(OpCodes.Ldfld, fb);
            numberGetIL.Emit(OpCodes.Ret);
            //保存动态创建的程序集
            dynamicAssembly.Save(DemoName.Name + ".dll");</span>

现在开始动态创建类:

构造函数: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吧,然后在来解释程序是如何执行的。

[csharp] view plain copy print ?
  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.         }  
<span style="font-size:14px;">/动态创建的动态类型
public static Type DynamicCreateType()
        {
            //动态创建程序集
            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", 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");
            //创建类
            return classType;
        }</span>



 

执行的主要方法


[csharp] view plain copy print ?
  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. }   
<span style="font-size:14px;">static void Main(string[] args)
{
    //动态创建的类类型
    Type classType = DynamicCreateType();
    //调用有参数的构造函数
    Type[] ciParamsTypes = new Type[] { typeof(string) };
    object[] ciParamsValues = new object[] { "Hello World" };
    ConstructorInfo ci = classType.GetConstructor(ciParamsTypes);
    object Vector = ci.Invoke(ciParamsValues);
    //调用方法
    object[] methedParams=new object[]{};
    Console.WriteLine(classType.InvokeMember("get_Field", BindingFlags.InvokeMethod, null, Vector, methedParams));
    Console.ReadKey();
} </span>


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



本文实例讲述了C#在运行时动态创建类型的实现方法。是C#项目开发中很实用的技巧。分享给大家供大家参考。具体分析如下:


具体来说,C# 在运行时动态的创建类型是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型的


主要功能代码如下:


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public static Assembly NewAssembly()
{
  //创建编译器实例。  
  provider = new CSharpCodeProvider();
  //设置编译参数。  
  cp = new CompilerParameters();
  cp.GenerateExecutable = false;
  cp.GenerateInMemory = true;
  
  // Generate an executable instead of 
  // a class library.
  //cp.GenerateExecutable = true;
  
  // Set the assembly file name to generate.
  cp.OutputAssembly = "c:\\1.dll";
  
  // Generate debug information.
  cp.IncludeDebugInformation = true;
  
  
  // Save the assembly as a physical file.
  cp.GenerateInMemory = false;
  
  // Set the level at which the compiler 
  // should start displaying warnings.
  cp.WarningLevel = 3;
  
  // Set whether to treat all warnings as errors.
  cp.TreatWarningsAsErrors = false;
  
  // Set compiler argument to optimize output.
  cp.CompilerOptions = "/optimize";
  
  cp.ReferencedAssemblies.Add("System.dll");
  //cp.ReferencedAssemblies.Add("System.Core.dll");
  cp.ReferencedAssemblies.Add("System.Data.dll");
  //cp.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
  cp.ReferencedAssemblies.Add("System.Deployment.dll");
  cp.ReferencedAssemblies.Add("System.Design.dll");
  cp.ReferencedAssemblies.Add("System.Drawing.dll");
  cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
  
  //创建动态代码。  
    
  StringBuilder classSource = new StringBuilder();
  classSource.Append("using System;using System.Windows.Forms;\npublic  class  DynamicClass: UserControl \n");
  classSource.Append("{\n");
  classSource.Append("public DynamicClass()\n{\nInitializeComponent();\nConsole.WriteLine(\"hello\");}\n");
  classSource.Append( "private System.ComponentModel.IContainer components = null;\nprotected override void Dispose(bool disposing)\n{\n");
  classSource.Append( "if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);\n}\n");
  classSource.Append( "private void InitializeComponent(){\nthis.SuspendLayout();this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);");
  classSource.Append( "this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.Name = \"DynamicClass\";this.Size = new System.Drawing.Size(112, 74);this.ResumeLayout(false);\n}");
  //创建属性。  
  /*************************在这里改成需要的属性******************************/
  classSource.Append(propertyString("aaa"));
  classSource.Append(propertyString("bbb"));
  classSource.Append(propertyString("ccc"));
  
  classSource.Append("}");
  
  System.Diagnostics.Debug.WriteLine(classSource.ToString());
   
  //编译代码。  
  CompilerResults result = provider.CompileAssemblyFromSource(cp, classSource.ToString());
  if (result.Errors.Count > 0)
  {
 for( int i = 0; i < result.Errors.Count; i ++)
   Console.WriteLine(result.Errors[ i]);
 Console.WriteLine("error");
 return null;
  }
    
  //获取编译后的程序集。  
  Assembly assembly = result.CompiledAssembly;
  
  return assembly;
}
  
private static string propertyString(string propertyName)
{
  StringBuilder sbProperty = new StringBuilder();
  sbProperty.Append(" private  int  _" + propertyName + "  =  0;\n");
  sbProperty.Append(" public  int  " + "" + propertyName + "\n");
  sbProperty.Append(" {\n");
  sbProperty.Append(" get{  return  _" + propertyName + ";}  \n");
  sbProperty.Append(" set{  _" + propertyName + "  =  value;  }\n");
  sbProperty.Append(" }");
  return sbProperty.ToString();
}


希望本文所述对大家的C#程序设计有所帮助


  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值