用于创建动态类型,并添加各个 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), 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();

    }

}

 http://blog.csdn.net/websco/archive/2010/03/10/5363666.aspx

posted @ 2010-03-27 10:08  周宏伟  阅读(339)  评论(0编辑  收藏  举报