動態建立類型及屬性–轉

來源:互聯網
上載者:User

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), type, FieldAttributes.Private);

 

        PropertyBuilder property = tb.DefineProperty(propertyNm, PropertyAttributes.HasDefault, type, null);

 

        MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

 

        if (canGet)

        {

            MethodBuilder getAccessor = tb.DefineMethod(string.Format("get_{0}", propertyNm), getSetAttr, type, 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}", propertyNm), getSetAttr, 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();

    }

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.