1. 程式人生 > >MSIL實用指南-生成屬性

MSIL實用指南-生成屬性

不能 play setattr ces reat 管理 set pty opc

本篇講解怎麽生成屬性,包括get和set方法。


第一步,生成一個字段
生成字段用TypeBuilder.DefineField方法。
實例代碼:

FieldBuilder customerNameBldr = typeBuilder.DefineField
("_CustomerName",typeof(string),FieldAttributes.Private);

第二步,創建一個PropertyBuilder對象
創建PropertyBuilder對象需要用生成字段用方法
TypeBuilder.DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)。
返回的是一個PropertyBuilder對象。
參數說明:
name: 屬性的名稱。name 不能包含嵌入的 null 值。
attributes: 屬性的特性。
returnType: 屬性的返回類型。
parameterTypes:屬性的參數類型。

實例代碼:

PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
("CustomerName", PropertyAttributes.HasDefault,typeof(string),null);

第三步,生成get和set方法
get和set方法的特性需要是 MethodAttributes.SpecialName | MethodAttributes.HideBySig ,
實例代碼:

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

get方法需要無參,返回類型與相關字段類型相同。
set方法需要一個參數,並且參數類型與相關字段的類型相同,無返回值。
實例代碼:

MethodBuilder custNameGetPropMthdBldr =
typeBuilder.DefineMethod("get_CustomerName", getSetAttr,typeof(string),Type.EmptyTypes);
MethodBuilder custNameSetPropMthdBldr =
typeBuilder.DefineMethod("set_CustomerName",getSetAttr,null,new
Type[] { typeof(string) });

第四步:實現get和set的方法體
這裏直接給一個實例
實例代碼:

ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
custNameGetIL.Emit(OpCodes.Ret);

ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
custNameSetIL.Emit(OpCodes.Ldarg_0);
custNameSetIL.Emit(OpCodes.Ldarg_1);
custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
custNameSetIL.Emit(OpCodes.Ret);


第五步,把get和set方法關聯到PropertyBuilder對象上
管理get和set方法分別用PropertyBuilder對象的SetGetMethod和SetSetMethod方法
實例代碼:

custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);

如果要生成一個只能get的屬性,那麽只要生成一個get方法,只調用SetGetMethod設置。
同理要生成一個只能set的屬性,那麽只要生成一個set方法,只調用SetSetMethod設置。


完整程序如下:

技術分享圖片
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace LX1_ILDemo
{
    class Demo11_Property
    {
        static string binaryName = "Demo11_Property.dll";
        static string namespaceName = "LX1_ILDemo";
        static string typeName = "PropertyDemo";

        static AssemblyBuilder assemblyBuilder;
        static ModuleBuilder moduleBuilder;
        static TypeBuilder typeBuilder;

        private static void  Generate_Property1()
        {
            FieldBuilder customerNameBldr = typeBuilder.DefineField
                ("_CustomerName",typeof(string),FieldAttributes.Private);

            PropertyBuilder custNamePropBldr = typeBuilder.DefineProperty
                ("CustomerName", PropertyAttributes.HasDefault,typeof(string),null);

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

            // 定義get方法
            MethodBuilder custNameGetPropMthdBldr =
                typeBuilder.DefineMethod("get_CustomerName", getSetAttr,typeof(string),Type.EmptyTypes);

            ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
            custNameGetIL.Emit(OpCodes.Ldarg_0);
            custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
            custNameGetIL.Emit(OpCodes.Ret);

            // 定義set方法
            MethodBuilder custNameSetPropMthdBldr =
                typeBuilder.DefineMethod("set_CustomerName",getSetAttr,null,new Type[] { typeof(string) });

            ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
            custNameSetIL.Emit(OpCodes.Ldarg_0);
            custNameSetIL.Emit(OpCodes.Ldarg_1);
            custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
            custNameSetIL.Emit(OpCodes.Ret);

            custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
            custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
        }

        private static void Generate_Property2()
        {
            FieldBuilder orgNameBldr = typeBuilder.DefineField
                ("_OrgName", typeof(string), FieldAttributes.Private);

            PropertyBuilder orgPropBldr = typeBuilder.DefineProperty
                ("OrgName", PropertyAttributes.HasDefault, typeof(string), null);

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

            MethodBuilder custNameGetPropMthdBldr =
                typeBuilder.DefineMethod("get_OrgName", getSetAttr, typeof(string), Type.EmptyTypes);

            ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();

            custNameGetIL.Emit(OpCodes.Ldarg_0);
            custNameGetIL.Emit(OpCodes.Ldfld, orgNameBldr);
            custNameGetIL.Emit(OpCodes.Ret);
            orgPropBldr.SetGetMethod(custNameGetPropMthdBldr);
        }

        public static void Generate()
        {
            InitAssembly();

            typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);

            Generate_Property1();
            Generate_Property2();

            SaveAssembly();
            Console.WriteLine("生成成功");
        }

        static void InitAssembly()
        {
            AssemblyName assemblyName = new AssemblyName(namespaceName);
            assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
        }

        static void SaveAssembly()
        {
            Type t = typeBuilder.CreateType(); //完成Type,這是必須的
            assemblyBuilder.Save(binaryName);
        }
    }
}
View Code

MSIL實用指南-生成屬性