微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

用于创建动态类型,并添加各个 public 属性的定义

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] 举报,一经查实,本站将立刻删除。

相关推荐