上一篇文章学习了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. JavaScript常见的五种数组去重的方式

    ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...

  2. 9、 Struts2验证(声明式验证、自定义验证器)

    1. 什么是Struts2 验证器 一个健壮的 web 应用程序必须确保用户输入是合法.有效的. Struts2 的输入验证 基于 XWork Validation Framework 的声明式验证: ...

  3. CSS 3学习——transform 2D转换

    首先声明一点,transform属性不为none的元素是它的定位子元素(绝对定位和固定定位)的包含块,而且对内创建一个新的层叠上下文. 注意:可以通过 transform-box 属性指定元素的那个盒 ...

  4. [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化

    KVM 虚拟化原理探究(5)- 网络IO虚拟化 标签(空格分隔): KVM IO 虚拟化简介 前面的文章介绍了KVM的启动过程,CPU虚拟化,内存虚拟化原理.作为一个完整的风诺依曼计算机系统,必然有输 ...

  5. 极光推送和友盟推送,ios端和安卓端的后端调试设置

    我是最后端的,这两天搞了一个app项目,前端安卓使用友盟很方便,调试比较顺利,然后ios就遇到各种问题了,证书.发送成功推送不成功,测试时用的TestMode(),ios上架之后就必须用product ...

  6. 新技术≠颠覆:CIO 要有战略耐心

    新技术≠颠覆:CIO 要有战略耐心 大数据,云时代,互联网思维, 物联网--最近一两年,这些字眼一次次地出现在各种大大小小的CIO会议上和他们的私下交流圈子里,作为对新技术最敏感的人群,一方面他们迫切 ...

  7. Android 算法 关于递归和二分法的小算法

     // 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1. package demo; public class Mytest { public st ...

  8. App 审核由于 IPv6 网络问题被拒

    昨天 提交App Store 的时候被拒了 We discovered one or more bugs in your app when reviewed on iPhone running iOS ...

  9. Android Weekly Notes Issue #235

    Android Weekly Issue #235 December 11th, 2016 Android Weekly Issue #235 本期内容包括: 开发一个自定义View并发布为开源库的完 ...

  10. ionic第一坑——ion-slide-box坑(ion-slide分两页的坑)

    ionic.views.Slider = ionic.views.View.inherit({ initialize: function (options) { . . . function setu ...