C#编程中可以给字段、方法、类以及程序集加特性即继承于Attribute的类。这里讲解怎么在IL中给
它们加上特性。

生成字段的对应的类是FieldBuilder,生成属性的对应的类是PropertyBuilder,生成方法的对应的
类是MethodBuilder,生成类型的对应的类是TypeBuilder,生成程序集的对应的类是AssemblyBuilder。
这些类都有一个共同的方法SetCustomAttribute,而且参数都是一样的,具体是
SetCustomAttribute(CustomAttributeBuilder customBuilder)

我们可以用这个方法给它们添加特性。

步骤1:用反射获得特性的ConstructorInfo
比如

Type attrType = typeof(SerializableAttribute);
ConstructorInfo infoConstructor = attrType.GetConstructor(new Type[] { });

步骤2:创建一个CustomAttributeBuilder
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor,<infoConstructor参数数组>);

步骤3:调用SetCustomAttribute方法
上面说的FieldBuilder等等都是有同样的SetCustomAttribute方法,所以调用程序也是一样。

完成的程序如下

using System;
using System.Reflection;
using System.Reflection.Emit; namespace LX1_ILDemo
{
public class Demo20_CustomAttribute
{
static string binaryName = "Demo20_CustomAttribute.dll";
static string namespaceName = "LX1_ILDemo";
static string typeName = "CustomAttributeDemo"; static AssemblyBuilder assemblyBuilder;
static ModuleBuilder moduleBuilder;
static TypeBuilder typeBuilder; public static void Generate()
{
InitAssembly();
typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public | TypeAttributes.Abstract);
Generate_Field();
Generate_Property();
Generate_Method();
TypeAddAttr();
AssemblyAddAttr();
SaveAssembly();
Console.WriteLine("生成成功");
} static void TypeAddAttr()
{
Type attrType = typeof(SerializableAttribute);
ConstructorInfo infoConstructor = attrType.GetConstructor(new Type[] { });
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] { });
typeBuilder.SetCustomAttribute(attributeBuilder);
} static void AssemblyAddAttr()
{
Type myType = typeof(AssemblyCopyrightAttribute);
ConstructorInfo infoConstructor = myType.GetConstructor(new Type[] { typeof(string) });
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] { "IL Test Copyright" });
assemblyBuilder.SetCustomAttribute(attributeBuilder);
} static void Generate_Method()
{
Type attrType = typeof(System.ObsoleteAttribute);
ConstructorInfo infoConstructor = attrType.GetConstructor(new Type[] { });
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] { }); MethodBuilder methodBuilder = typeBuilder.DefineMethod("Test",
MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
typeof(void), new Type[] { }); methodBuilder.SetCustomAttribute(attributeBuilder);
} static void Generate_Field()
{
Type attrType = typeof(System.ObsoleteAttribute);
ConstructorInfo infoConstructor = attrType.GetConstructor(new Type[] { });
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] { });
FieldBuilder fieldBuilder = typeBuilder.DefineField("Name", typeof(string), FieldAttributes.Private);
fieldBuilder.SetCustomAttribute(attributeBuilder);
} static void Generate_Property()
{
FieldBuilder fieldBuilder = typeBuilder.DefineField
("_Area", typeof(string), FieldAttributes.Private); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty
("Area", PropertyAttributes.HasDefault, typeof(string), null); MethodAttributes getSetAttr =
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; MethodBuilder _methodBuilder =
typeBuilder.DefineMethod("get_Area", getSetAttr, typeof(string), Type.EmptyTypes); ILGenerator custNameGetIL = _methodBuilder.GetILGenerator(); custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, fieldBuilder);
custNameGetIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(_methodBuilder); Type attrType = typeof(ObsoleteAttribute);
ConstructorInfo infoConstructor = attrType.GetConstructor(new Type[] { });
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(infoConstructor, new object[] { });
propertyBuilder.SetCustomAttribute(attributeBuilder);
} 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);
}
}
}

MSIL实用指南-给字段、属性、方法、类、程序集加Attribute的更多相关文章

  1. MSIL实用指南-创建字段

    本篇讲解怎么创建字段,主要是在修饰符的创建上. 创建字段的方法是TypeBuilder.DefineField,传入字段名称.字段类型.字段修饰符等参数,返回一个FieldBuilder对象.先看这一 ...

  2. MSIL实用指南-生成索引器

    MSIL实用指南-生成索引器 索引器是一种特殊的属性,它有参数的,也有get和set方法,属性名称一般是"Item",并且方法名称一般名称是"get_Item" ...

  3. c#基础3-方法的重载静态和非静态,字段属性,方法

    方法的重载概念:方法的重载指的就是方法的名称相同给,但是参数不同.参数不同,分为两种情况1).如果参数的个数相同,那么参数的类型就不能相同.2).如果参数的类型相同,那么参数的个数就不能相同.***方 ...

  4. MSIL实用指南-Action的生成和调用

    MSIL实用指南-Action的生成和调用 System.Action用于封装一个没有参数没有返回值的方法.这里生成需要Ldftn指令. 下面讲解怎生成如下的程序. class ActionTest ...

  5. C#-类 字段 属性 方法 特性

    方法的签名 包括参数个数.参数类型.方法返回值 base和this关键字 1.使用base关键字,就可以使用父类中的字段.属性.方法 2.一旦父类中存在有参数的构造函数,那么子类就必须使用base来覆 ...

  6. MSIL实用指南-生成属性

    本篇讲解怎么生成属性,包括get和set方法. 第一步,生成一个字段生成字段用TypeBuilder.DefineField方法.实例代码: FieldBuilder customerNameBldr ...

  7. MSIL实用指南-struct的生成和操作

    struct(结构)是一种值类型,用于将一组相关的信息变量组织为一个单一的变量实体.所有的结构都继承自System.ValueType类,因此是一种值类型,也就是说,struct实例分配在线程的堆栈( ...

  8. MSIL实用指南-创建方法和定义参数

    本篇讲解实现创建方法.指定参数的名称.实现参数加out和ref修饰符.以及参数加默认值. 创建方法 创建方法用类TypeAttributes的 DefineMethod(string name, Me ...

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

    字段有静态字段和非静态字段之分,它们的加载保存指令也是不一样的,并且非静态字段要生成this. 静态字段的加载加载静态字段的指令是Ldsfld.ilGenerator.Emit(OpCodes.Lds ...

随机推荐

  1. Oculus Rift 没有声音的解决方法

    If you do not hear any audio when using Rift, please try the following steps: Check the Rift audio s ...

  2. lr录制选项设置代理

    解决录制时浏览器打不开录制时录不到脚本等浏览器兼容问题一.lr录制选项设置代理1.点击Options 2.点击Port Mapping→Newentrv 3.lr代理设置 ·Socket Servic ...

  3. 我是这样一步步理解--主题模型(Topic Model)、LDA

    1. LDA模型是什么 LDA可以分为以下5个步骤: 一个函数:gamma函数. 四个分布:二项分布.多项分布.beta分布.Dirichlet分布. 一个概念和一个理念:共轭先验和贝叶斯框架. 两个 ...

  4. vuex快速入门

    vuex是什么? vuex是一个专门为vue.js应用程序开发的状态管理模式. vuex默认的五种基本的对象: state:存储状态(可以理解为变量)可以从计算属性中返回某个状态 getters:通常 ...

  5. NDK jni mk文件 so文件 巴啦啦 初体验

    概念JNI(Java Native Interface,Java本地接口),实现了Java和其他语言的交互(主要是C/C++),如:Java程序通过JNI调用C/C++编写的在Windows上运行的D ...

  6. tensorflow学习笔记——常见概念的整理

    TensorFlow的名字中已经说明了它最重要的两个概念——Tensor和Flow.Tensor就是张量,张量这个概念在数学或者物理学中可以有不同的解释,但是这里我们不强调它本身的含义.在Tensor ...

  7. OV SSL证书有哪些功能?网站安装OV SSL证书的好处

    OV SSL证书英文名称为Organization Validation SSL Certificate,申请OV SSL证书需要审核申请者对域名是否拥有控制权,同时审核申请者是否为一个合法登记.真实 ...

  8. ipv6的连接

    基础知识不说了,网上一大堆! 基本内容不说了,写字太累了! 只说三点细节,记住就行: 1.ff开头的是多播地址,只能用于udp多播 2.fe80开头的是本地link地址,不管ping也好,connec ...

  9. 自定义itemCheckView

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  10. python基础之变量与数据类型

    变量在python中变量可以理解为在计算机内存中命名的一个存储空间,可以存储任意类型的数据.变量命名变量名可以使用英文.数字和_命名,且不能用数字开头使用赋值运算符等号“=”用来给变量赋值.变量赋值等 ...