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信息也是模块的一部分。多个模块组建成一个程序集。

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

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

//动态创建程序集
AssemblyNameDemoName=newAssemblyName("DynamicAssembly");
AssemblyBuilderdynamicAssembly=AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName,AssemblyBuilderAccess.RunAndSave);
//动态创建模块
ModuleBuildermb=dynamicAssembly.DefineDynamicModule(DemoName.Name,DemoName.Name+".dll");
//动态创建类MyClass
TypeBuildertb=mb.DefineType("MyClass",TypeAttributes.Public);
//动态创建字段
FieldBuilderfb=tb.DefineField("",typeof(System.String),FieldAttributes.Private);
//动态创建构造函数
Type[]clorType=newType[]{typeof(System.String)};
ConstructorBuildercb1=tb.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,clorType);
//生成指令
ILGeneratorilg=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);
//动态创建属性
PropertyBuilderpb=tb.DefineProperty("MyProperty",PropertyAttributes.HasDefault,typeof(string),null);
//动态创建方法
MethodAttributesgetSetAttr=MethodAttributes.Public|MethodAttributes.SpecialName;
MethodBuildermyMethod=tb.DefineMethod("get_Property",getSetAttr,typeof(string),Type.EmptyTypes);
//生成指令
ILGeneratornumberGetIL=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吧,然后在来解释程序是如何执行的。

/动态创建的动态类型

publicstaticTypeDynamicCreateType()
{
//动态创建程序集
AssemblyNameDemoName=newAssemblyName("DynamicAssembly");
AssemblyBuilderdynamicAssembly=AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName,AssemblyBuilderAccess.RunAndSave);
//动态创建模块
ModuleBuildermb=dynamicAssembly.DefineDynamicModule(DemoName.Name,DemoName.Name+".dll");
//动态创建类MyClass
TypeBuildertb=mb.DefineType("MyClass",TypeAttributes.Public);
//动态创建字段
FieldBuilderfb=tb.DefineField("myField",typeof(System.String),FieldAttributes.Private);
//动态创建构造函数
Type[]clorType=newType[]{typeof(System.String)};
ConstructorBuildercb1=tb.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,clorType);
//生成指令
ILGeneratorilg=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);
//动态创建属性
PropertyBuilderpb=tb.DefineProperty("MyProperty",PropertyAttributes.HasDefault,typeof(string),null);
//动态创建方法
MethodAttributesgetSetAttr=MethodAttributes.Public|MethodAttributes.SpecialName;
MethodBuildermyMethod=tb.DefineMethod("get_Field",getSetAttr,typeof(string),Type.EmptyTypes);
//生成指令
ILGeneratornumberGetIL=myMethod.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld,fb);
numberGetIL.Emit(OpCodes.Ret);
//使用动态类创建类型
TypeclassType=tb.CreateType();
//保存动态创建的程序集(程序集将保存在程序目录下调试时就在Debug下)
dynamicAssembly.Save(DemoName.Name+".dll");
//创建类
returnclassType;
}


执行的主要方法


staticvoidMain(string[]args)
{
//动态创建的类类型
TypeclassType=DynamicCreateType();
//调用有参数的构造函数
Type[]ciParamsTypes=newType[]{typeof(string)};
object[]ciParamsValues=newobject[]{"HelloWorld"};
ConstructorInfoci=classType.GetConstructor(ciParamsTypes);
objectVector=ci.Invoke(ciParamsValues);
//调用方法
object[]methedParams=newobject[]{};
Console.WriteLine(classType.InvokeMember("get_Property",BindingFlags.InvokeMethod,null,Vector,methedParams));
Console.ReadKey();
}

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

<wbr></wbr>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值