C#动态创建和动态使用程序集、类、方法、字段等
来源:互联网 发布:php语言用什么软件 编辑:程序博客网 时间:2024/05/06 20:20
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信息也是模块的一部分。多个模块组建成一个程序集。
所谓动态就是在程序运行时,动态的创建和使用。
直接看代码吧,其实超级简单。
- //动态创建程序集
- 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");
现在开始动态创建类:
构造函数: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吧,然后在来解释程序是如何执行的。
- /动态创建的动态类型
- 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;
- }
执行的主要方法
- 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();
- }
我创建了一个类,类里创建了有一个字段、有一个参数的构造函数、一个属性、有一个参数的构造函数和一个方法。用有参数的构造函数来初始化字段myField,然后调用get_Field方法返回myField字段的值。控制台程序显示“Hello World!!!”
本文实例讲述了C#在运行时动态创建类型的实现方法。是C#项目开发中很实用的技巧。分享给大家供大家参考。具体分析如下:
具体来说,C# 在运行时动态的创建类型是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型的。
主要功能代码如下:
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#程序设计有所帮助
- C#动态创建和动态使用程序集、类、方法、字段等
- C#动态创建和动态使用程序集、类、方法、字段等
- C#动态创建和动态使用程序集、类、方法、字段等
- C#动态创建和动态使用程序集、类、方法、字段等
- [.Net码农]C#动态创建和动态使用程序集、类、方法、字段等(一)
- [.Net码农]C#动态创建和动态使用程序集、类、方法、字段等(二)
- C#动态创建和动态使用程序集、类、方法、字段等
- C#动态创建类和使用特性增强程序可扩展性
- C#动态加载创建程序集
- c# 动态编译创建程序集
- 动态创建程序集
- 【Objective-C Runtime动态加载】---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_
- C#动态生成代码和程序集
- 使用cglib动态创建类,添加方法
- C# 动态调用类方法和属性
- C#中创建和使用资源动态链接库
- C#中创建和使用资源动态链接库
- 创建和使用动态链接库 (C++)C#调用
- 单链表操作,队列,栈实现,以及常见字符串库函数经典实现
- 使用Python写一个小小的项目监控
- 看到的面试题,请容我一道一道的解析(假以时日),希望大家留言一起探讨~
- import com.sun.image.codec.jpeg.JPEGCodec不通过 找不到包
- cocos2dx接入SDK记事本
- C#动态创建和动态使用程序集、类、方法、字段等
- Android 设置Activity样式 透明度
- java 多线程 ThreadPoolExecutor 接收并处理数据
- 一个 BC4J 的问题
- H264 Intro - slice type
- 自定义textview
- leetCode #125 Valid Palindrome
- PyQt4学习资料汇总
- 黑马程序员--Java基础之内部类