上一篇文章学习了IL的入门,接下来我们再通过两个例子来了解下类的属性、构造函数以及接口的使用

一、类的属性、构造函数

1、先看下我们要构建的类的C#代码,然后再进行IL的实现,示例代码如下:

    [Serializable]
    public class Dynamic
    {
        ;
        public const string ConstField = "const";

        /// <summary>
        /// 定义属性
        /// </summary>
        public int A { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="num"></param>
        public Dynamic(int num)
        {
            this.A = num;
        }

        public int Add(int num)
        {
            return this.A + num;
        }
    }

2、通过以上代码我们可以根据要求先定义字段_a、常量ConstField(在构造函数过程中未使用到,帮组了解类属性的创建)以及给类加上序列化标签,属性可以通过TypeBuilder的DefineField创建,而序列化标签需要通过TypeBuilder的CustomAttributeBuilder去创建,示例代码如下:

            //定义类可序列化
            CustomAttributeBuilder serializable = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { });
            typeBuilder.SetCustomAttribute(serializable);

            //定义常量
            FieldBuilder fieldConst = typeBuilder.DefineField("ConstField", typeof(string), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal);
            fieldConst.SetConstant("const");

            //定义字段_a
            FieldBuilder aField = typeBuilder.DefineField("_a", typeof(int), FieldAttributes.Private);
            aField.SetConstant();

3、通过TypeBuilder的DefineProperty定义属性A,通过CustomAttributeBuilder给属性添加对应的标签,示例代码如下:

            //定义属性A
            PropertyBuilder propertyABuilder = typeBuilder.DefineProperty("A", PropertyAttributes.None, typeof(int), null);
            CustomAttributeBuilder desAttributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { "属性A" });
            propertyABuilder.SetCustomAttribute(desAttributeBuilder);//字段描述

4、定义A属性的get方法和set方法,get和set方法和普通的方法创建相同,用TypeBuilder的DefineMethod创建。示例代码如下:

            //定义属性get方法
            MethodBuilder methodABuilder = typeBuilder.DefineMethod("get", MethodAttributes.Public, typeof(Int32), Type.EmptyTypes);
            ILGenerator GetIL = methodABuilder.GetILGenerator();
            GetIL.Emit(OpCodes.Ldarg_0);
            GetIL.Emit(OpCodes.Ldfld, aField);
            GetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetGetMethod(methodABuilder);

            //定义属性set方法
            MethodBuilder methodBBuilder = typeBuilder.DefineMethod("set", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(Int32) });
            ILGenerator SetIL = methodBBuilder.GetILGenerator();
            SetIL.Emit(OpCodes.Ldarg_0);
            SetIL.Emit(OpCodes.Ldarg_1);
            SetIL.Emit(OpCodes.Stfld, aField);
            SetIL.Emit(OpCodes.Ret);
            propertyABuilder.SetSetMethod(methodBBuilder);

5、构造函数的创建,构造函数是通过TypeBuilder的DefineConstructor去获取,构造函数包含一个参数并赋值给_a,示例代码如下:

            //定义构造函数
            ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32) });

            ILGenerator constructorIL = constructorBuilder.GetILGenerator();
            constructorIL.Emit(OpCodes.Ldarg_0);
            constructorIL.Emit(OpCodes.Ldarg_1);
            constructorIL.Emit(OpCodes.Stfld, aField);
            constructorIL.Emit(OpCodes.Ret);

6、最后是定义方法。

            //定义方法
            MethodBuilder methodAddBuild = typeBuilder.DefineMethod("Add", MethodAttributes.Public, typeof(Int32), new Type[] { typeof(int) });
            ILGenerator addIL = methodAddBuild.GetILGenerator();
            addIL.Emit(OpCodes.Ldarg_0);
            addIL.Emit(OpCodes.Ldfld, aField);
            addIL.Emit(OpCodes.Ldarg_1);
            addIL.Emit(OpCodes.Add);
            addIL.Emit(OpCodes.Ret);

到这一步一个动态类包含的属性、构造函数以及方法就创建完成。可以借助reflector看下生成的结果。如下:

public int A { get; set; }
换成
public int A5
{
get { return _a; }
set { _a = value; }
}
比较容易理解_a的存在

 二、接口的实现

1、首先我们看下我们要实现一个什么样的接口,先看下构建类的C#代码,示例代码如下:

    public class Mail : IMail
    {

        public string SendMail()
        {
            return "Send Success";
        }
    }

    public interface IMail
    {
        string SendMail();
    }

2、实现接口,接口我们直接用IMail这个。就不用IL去创建了,首先我们创建一个typeBuilder,指定继承接口IMail,可以用AddInterfaceImplementation来进行操作。示例代码如下:

            //定义类型
            TypeBuilder typeBuilder = moduleBuilder.DefineType(name, TypeAttributes.Public);
            typeBuilder.AddInterfaceImplementation(typeof(IMail));

3、实现接口。接口实现方法要怎么定义在不清楚的情况下可以用reflector反编译一个实现接口的方法来查看一下,观察一下方法需要哪些MethodAttributes属性。

通过以上信息可以定义接口实现的方法,接口实现就和之前例子定义的方法实现一样。示例代码如下:

            MethodBuilder sendMailBuilder = typeBuilder.DefineMethod("SendMail", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), null);
            //定义接口
            ILGenerator mailIL = sendMailBuilder.GetILGenerator();
            LocalBuilder resultStr = mailIL.DeclareLocal(typeof(String));
            mailIL.Emit(OpCodes.Nop);
            mailIL.Emit(OpCodes.Ldstr, "Send Success1");
            mailIL.Emit(OpCodes.Stloc_0);
            mailIL.Emit(OpCodes.Ldloc_0);
            mailIL.Emit(OpCodes.Ret);

实现后通过IL查看的代码如下:

反编译发现,接口实现是带有override关键字的。而在定义实现方法时候如果不带上virtual属性又会提示接口未实现。。。。。。

通过这篇文章我们了解到了动态类的创建,也了解到了接口的使用。从这两个示例其实可以拓展出很多的东西比如继承、属性绑定自定义标签、虚方法的重写......以后再一一分享
示例代码下载:IL-3

IL接口和类的属性的更多相关文章

  1. Hibernate(三)__核心接口和类

    该图显示了核心接口类以及配置文件的关系层次,越往下越偏向底层数据库. 1. hibernate.cfg.xml文件 ①该文件主要用于指定各个参数,是hibernate核心文件 ②默认放在src目录下, ...

  2. Servlet API遍程常用接口和类

    本文主要总结Servlet  API遍程常用接口和类 Servlet API http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html ...

  3. Spring常用的接口和类(二)

    七.BeanPostProcessor接口 当需要对受管bean进行预处理时,可以新建一个实现BeanPostProcessor接口的类,并将该类配置到Spring容器中. 实现BeanPostPro ...

  4. Spring常用的接口和类(一)

    一.ApplicationContextAware接口 当一个类需要获取ApplicationContext实例时,可以让该类实现ApplicationContextAware接口.代码展示如下: p ...

  5. ibernate学习笔记5---实体类或属性名与数据库关键字冲突、hql命名参数、hql实现通用分页

    一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 ...

  6. (转)beanUtil接口和类(有空的时候去看,到时候删除这个说明)

    Jakarta Commons项目提供了相当丰富的API,我们之前了解到的Commons Lang只是众多API的比较核心的一小部分而已.Commons下面还有相当数量的子项目,用于解决各种各样不同方 ...

  7. 一张图让你快速学会UML(聚合、组合、依赖、继承、接口、类)

    有朋友反映,一上来直接讲设计模式就算理解了,也不知道如何画出类图,那么我们就通过一张图,来图解如何应用UML正确表示类与类之间的关系. 这张图完整讲述了鸟类的生存. 首先是类:在UML中,我们用分成三 ...

  8. XML之自动生成类,添加,修改,删除类的属性

    1. class ClassHelperDemo { public static void Main() { #region 演示一:动态生成类. //生成一个类t. Type t = ClassHe ...

  9. Spring常用接口和类

    一.ApplicationContextAware接口 当一个类需要获取ApplicationContext实例时,可以让该类实现ApplicationContextAware接口.代码展示如下: p ...

随机推荐

  1. SQL Server-聚焦在视图和UDF中使用SCHEMABINDING(二十六)

    前言 上一节我们讨论了视图中的一些限制以及建议等,这节我们讲讲关于在UDF和视图中使用SCHEMABINDING的问题,简短的内容,深入的理解,Always to review the basics. ...

  2. 简析服务端通过GT导入SHP至PG的方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在浏览器端直接上传SHP后服务端进行数据的自动入PG ...

  3. [内核笔记1]内核文件结构与缓存——inode和对应描述

    由来:公司内部外网记录日志的方式现在都是通过Nginx模块收到数据发送到系统消息队列,然后由另外一个进程来从消息队列读取然后写回磁盘这样的操作,尽量的减少Nginx的阻塞. 但是由于System/V消 ...

  4. 【JQ基础】DOM操作

    内部插入:append() //向每个匹配的元素内部追加内容,可包含 HTML 标签 $(selector).append(function(index,html)) /*•index - 可选.接收 ...

  5. SAP自定义权限对象

    SAP系统自带了很多的权限对象,每一个运行画面都有非常多的权限用到.不过标准的权限对象并不一定适合于用在客户自己开发的程序里面,所以每个ABAPer都应该会自己开发一套权限对象,并引用在程序代码里面. ...

  6. 电脑新建svn仓库

    步骤1:安转svg: 注意事项: 安装的时候选择:Modify 安装到以下图片的步骤时: 黄色区域选择: 步骤2:新建svn仓库文件夹(本教程例子:D:\svn-5gpos),选择文件夹右键,点击下图 ...

  7. mac好用的markdown编辑器

    在刚开始接触markdown的时候,就被吸引了.此后一直在找贴心的好用的markdown编辑器.印象笔记和马克飞象配合着用也是挺好的,唯一的缺点就是比较封闭,发个笔记的链接给同学,还得注册才能看,导致 ...

  8. Mysql - 函数

    Mysql提供的函数是在是太多了, 很多我都见过, 别说用了. 园子里面, 有人弄了一个比较全的. MYSQL函数 我这里会将他写的完全拷贝下来, 中间会插入一些自己项目中使用过的心得 一.数学函数 ...

  9. windows下mongodb配置

    打开cmd(windows键+r输入cmd)命令行,进入D:\mongodb\bin目录(如图先输入d:进入d盘然后输入cd d:\mongodb\bin), 输入如下的命令启动mongodb服务: ...

  10. 从myeclipse导入eclipse,不能识别为web项目(java项目转为web项目)

    1.进入项目目录,找到.project文件,打开. 2.找到<natures>...</natures>代码段. 3.在第2步的代码段中加入如下标签内容并保存:         ...