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);
        }
    }
}

原文地址:https://www.cnblogs.com/tkt2016/p/8630142.html

时间: 2024-10-09 13:32:04

MSIL实用指南-生成属性的相关文章

MSIL实用指南-生成for语句

for语句格式是这样的for(<初始化语句>;<条件语句>;<自增减语句>) <循环体> 它可以转换为while语句 if(<条件语句>){ <初始化语句> while(<条件语句>) { <循环体> <自增减语句> }} 那么就可以按照这while语句生成. 原文地址:https://www.cnblogs.com/tkt2016/p/8807388.html

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

闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭包是在其词法上下文中引用了自由变量(注1)的函数.另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体.比如参考资源中就有这样的的定义:在实现深约束(注2)时,需要创建一个能显式表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包.这两种定义在某种意义上是对立的,

MSIL实用指南-类相关生成

一.创建class用MethodBuilder的DefineType方法,可以指定父类,得到一个TypeBuilder对象. 二.实现继承接口用TypeBuilder的AddInterfaceImplementation方法. 三.显示方法重写用TypeBuilder的DefineMethodOverride方法. 完整代码如下: using System; using System.Reflection; using System.Reflection.Emit; namespace LX1_

MSIL实用指南-加载null、string、long、float、double等值

本篇讲述怎么加载null.string值.long值.float值.double值. 加载null不需要参数值,只要 Emit ldnull 其它几个命令要 Emit <指令> <值> 加载null 加载null是很简单的,使用OpCodes.Ldnull,以下一句程序就可以了. ilGenerator.Emit(OpCodes.Ldnull); 加载string值 加载string值也很简单,使用OpCodes.Ldstr,格式是 ilGenerator.Emit(OpCodes

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

字段有静态字段和非静态字段之分,它们的加载保存指令也是不一样的,并且非静态字段要生成this. 静态字段的加载加载静态字段的指令是Ldsfld.ilGenerator.Emit(OpCodes.Ldsfld, <FieldBuilder>);实际例子 ilGenerator.Emit(OpCodes.Ldsfld, areaFieldBuilder); ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); 静态字段的保存保存静态字段的指令

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

一.类的强制转换1.转换成某个类用Castclass指令.实例代码:ilGenerator.Emit( OpCodes.Castclass , typeof(ClassA) ); 2.转换成某个值类型用Unbox_Any指令.实例代码:ilGenerator.Emit( OpCodes.Unbox_Any , typeof(DateTime) );ilGenerator.Emit( OpCodes.Unbox_Any , typeof(int) ); 二.值类型的强制转换 1.转化为sbyte用

Docker实用指南:将Python Web应用容器化

Docker实用指南:将Python Web应用容器化 提供 Zstack社区 前言 Web应用随时可能被攻击者利用来夺取整个主机的权限,这是很常见也是很恐怖的一件事.为了更高的安全性,就需要将不同应用之间进行隔离(尤其是在这些应用属于不同的用户的情况下),然而这种隔离的实现一直是个挑战.到目前为止,隔离性的实现方法已经有了很多,然而它们要么太过昂贵(时间的层面以及资源的层面),要么太过复杂(无论对开发者还是对管理员). 本文将讨论如何让"容器化"的Python Web应用跑在安全的沙

交互设计实用指南系列11-减少记忆负担

转载: http://ued.taobao.org/blog/2010/03/交互设计实用指南系列11-减少记忆负担/ 科普 <辞海>中“记忆”的定义是:“人脑对经验过的事物的识记.保持.再现或再认.”记忆是人类一个非常重要的心理活动,它是人类很多其他思维活动和行为的基础.在所有的认知心理活动中,记忆和软件交互的关系最为密切.我们脑内的神经元反映的信息在需要用的时候可以被准确的再次呈现,也就是储存在DNA链上的信息基因,在适当条件下,指导合成信息蛋白并呈现的过程.在信息处理的角度,我们都关心怎

《Android Studio实用指南》4.27 使用演示模式

本文节选自<Android Studio实用指南> 第4章第27节 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. 什么是演示模式? 顾名思义,当你想给别人演示你的代码时就会用到这个演示模式. 演示模式的特点就是全屏,开启免打扰模式, 工具栏.状态栏等全部被隐藏,同时代码字体会被放大, 这样大家就会更专注于代码. 进入演示模式 操作步骤: ? 菜单栏: View —> Enter Presentation Mode 效果如下