using System;
using System.Reflection;
using System.Reflection.Emit;
/// <summary>
/// 用于创建动态类型,并添加各个 public 属性的定义
/// </summary>
public class DynamicTypeBuilder
{
TypeBuilder tb;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="typeNm">动态类型的名称</param>
public DynamicTypeBuilder(string typeNm)
{
// 在 Silverlight 中 AssemblyBuilderAccess 没有 RunAndSave
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("TempAssembly"),AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule("TempModule");
this.tb = mb.DefineType(typeNm,TypeAttributes.Public);
}
/// <summary>
/// 添加一个public的可读写属性,并且会创建对应的名为 propertyNm + "Field" 的私有字段
/// </summary>
/// <param name="propertyNm"></param>
/// <param name="type"></param>
public void AppendPublicProperty(string propertyNm,Type type)
{
this.AppendPublicProperty(propertyNm,type,true,true);
}
/// <summary>
/// 添加一个public属性,并且会创建对应的名为 propertyNm + "Field" 的私有字段
/// </summary>
/// <param name="propertyNm"></param>
/// <param name="type"></param>
/// <param name="canGet">是否实现getter</param>
/// <param name="canSet">是否实现setter</param>
public void AppendPublicProperty(string propertyNm,Type type,bool canGet,bool canSet)
{
FieldBuilder field = this.tb.DefineField(string.Format("{0}Field",propertyNm),FieldAttributes.Private);
PropertyBuilder property = tb.DefineProperty(propertyNm,PropertyAttributes.HasDefault,null);
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
if (canGet)
{
MethodBuilder getAccessor = tb.DefineMethod(string.Format("get_{0}",getSetAttr,Type.EmptyTypes);
ILGenerator getIL = getAccessor.GetILGenerator();
#region 按照 IL 代码的写法
// 按照 IL 代码的写法,不能运行
//.method public hidebysig specialname instance int32
// get_A() cil managed
//{
// // Code size 12 (0xc)
// .maxstack 1
// .locals init ([0] int32 CS$1$0000)
// IL_0000: nop
// IL_0001: ldarg.0
// IL_0002: ldfld int32 WpfApplication2.Person::AField
// IL_0007: stloc.0
// IL_0008: br.s IL_000a
// IL_000a: ldloc.0
// IL_000b: ret
//} // end of method Person::get_A
// 按照上面 IL 代码的写法,不能运行 :
//Label getBrsLabel = getIL.DefineLabel();
//getIL.Emit(OpCodes.nop);
//getIL.Emit(OpCodes.Ldarg_0);
//getIL.Emit(OpCodes.Ldfld,field);
//getIL.Emit(OpCodes.Stloc_0);
//getIL.Emit(OpCodes.Br_S,getBrsLabel);
//getIL.MarkLabel(getBrsLabel);
//getIL.Emit(OpCodes.Ldloc_0);
//getIL.Emit(OpCodes.Ret);
#endregion
// For an instance property,argument default is the instance. Load the
// instance,then load the private field and return,leaving the
// field value on the stack.
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld,field);
getIL.Emit(OpCodes.Ret);
property.Setgetmethod(getAccessor);
}
if (canSet)
{
MethodBuilder setAccessor = tb.DefineMethod(string.Format("set_{0}",null,new Type[] { type });
setAccessor.DefineParameter(1,Parameterattributes.None,"value");
ILGenerator setIL = setAccessor.GetILGenerator();
// Load the instance and then the numeric argument,then store the
// argument in the field.
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld,field);
setIL.Emit(OpCodes.Ret);
property.SetSetMethod(setAccessor);
}
}
/// <summary>
/// 在添加完各个 public 属性之后,调用此方法以完成对动态类型的定义并加载之,
/// 此后通过 Activator.CreateInstance() 便可实例化动态类型
/// </summary>
/// <returns></returns>
public Type CreateDynamicType()
{
return this.tb.CreateType();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。