IL接口和类的属性
上一篇文章学习了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接口和类的属性的更多相关文章
- Hibernate(三)__核心接口和类
该图显示了核心接口类以及配置文件的关系层次,越往下越偏向底层数据库. 1. hibernate.cfg.xml文件 ①该文件主要用于指定各个参数,是hibernate核心文件 ②默认放在src目录下, ...
- Servlet API遍程常用接口和类
本文主要总结Servlet API遍程常用接口和类 Servlet API http://tomcat.apache.org/tomcat-5.5-doc/servletapi/index.html ...
- Spring常用的接口和类(二)
七.BeanPostProcessor接口 当需要对受管bean进行预处理时,可以新建一个实现BeanPostProcessor接口的类,并将该类配置到Spring容器中. 实现BeanPostPro ...
- Spring常用的接口和类(一)
一.ApplicationContextAware接口 当一个类需要获取ApplicationContext实例时,可以让该类实现ApplicationContextAware接口.代码展示如下: p ...
- ibernate学习笔记5---实体类或属性名与数据库关键字冲突、hql命名参数、hql实现通用分页
一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 ...
- (转)beanUtil接口和类(有空的时候去看,到时候删除这个说明)
Jakarta Commons项目提供了相当丰富的API,我们之前了解到的Commons Lang只是众多API的比较核心的一小部分而已.Commons下面还有相当数量的子项目,用于解决各种各样不同方 ...
- 一张图让你快速学会UML(聚合、组合、依赖、继承、接口、类)
有朋友反映,一上来直接讲设计模式就算理解了,也不知道如何画出类图,那么我们就通过一张图,来图解如何应用UML正确表示类与类之间的关系. 这张图完整讲述了鸟类的生存. 首先是类:在UML中,我们用分成三 ...
- XML之自动生成类,添加,修改,删除类的属性
1. class ClassHelperDemo { public static void Main() { #region 演示一:动态生成类. //生成一个类t. Type t = ClassHe ...
- Spring常用接口和类
一.ApplicationContextAware接口 当一个类需要获取ApplicationContext实例时,可以让该类实现ApplicationContextAware接口.代码展示如下: p ...
随机推荐
- 手动导入swift三方danielgindi/Charts到OC工程中教程
1.到github网址上下载zip压缩包https://github.com/danielgindi/Charts 2.然后将解压后的文件夹整个拖到自己的工程文件夹下(很多教程只让拖xcodeproj ...
- https 安全验证问题
最近为了满足苹果的 https 要求, 经过努力终于写出了方法 验证 SSL 证书是否满足 ATS 要求 nscurl --ats-diagnostics --verbose https://你的域名 ...
- Linux命令【第一篇】
1.创建一个目录/data 记忆方法:英文make directorys缩写后就是mkdir. 命令: mkdir /data 或 cd /;mkdir data #提示:使用分号可以在一行内分割两个 ...
- 打开程序总是会提示“Enter password to unlock your login keyring” ,如何成功关掉?
p { margin-bottom: 0.1in; line-height: 120% } 一.一开始我是按照网友所说的 : rm -f ~/.gnome2/keyrings/login.keyrin ...
- 转: 如何高效利用GitHub
注:写了很多使用哲学,有意思 from: http://www.yangzhiping.com/tech/github.html
- 微信小程序之用户数据解密(七)
[未经作者本人同意,请勿以任何形式转载] 经常看到有点的小伙伴在群里问小程序用户数据解密流程,所以打算写一篇关于小程序用户敏感数据解密教程: 加密过程微信服务器完成,解密过程在小程序和自身服务器完成, ...
- 如何快速开发SPA应用
前言 web早已经进入了2.0时代了,如今的网页大有往系统应用级别的方向发展的趋势,再也不是以前的简单展示信息的界面了.如今很多webapp已经做到了原生应用的功能,并且运用自身的优势逐步取代之.HT ...
- .NET基础拾遗(3)字符串、集合和流
Index: (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基础 ...
- 【完全开源】知乎日报UWP版(下篇):商店APP、github源码、功能说明。Windows APP 良心出品。
目录 说明 功能 截图+视频 关于源码和声明 说明 陆陆续续大概花了一个月的时间,APP算是基本完成了.12月份一直在外出差,在出差期间进行了两次功能完善,然后断断续续修补了一些bug,到目前为止,我 ...
- android内部培训视频_第五节(1)_OA实战之登录界面
第五节(1):OA实战之登录界面 一.登录界面布局 1.背景图片 2.文本框 3.checkbox 4.按钮 暂未实现点击切换图片效果 <RelativeLayout xmlns:androi ...