MSIL实用指南-生成属性

Posted TKT2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MSIL实用指南-生成属性相关的知识,希望对你有一定的参考价值。

本篇讲解怎么生成属性,包括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实用指南-生成属性的主要内容,如果未能解决你的问题,请参考以下文章

MSIL实用指南-比较运算

MSIL实用指南-生成for语句

MSIL实用指南-闭包的生成和调用

MSIL实用指南-字段的加载和保存

MSIL实用指南-数据类型转换

MSIL实用指南-方法的调用