[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的反射的实现方法,通过对反射性特的了解,可以设计出非常有用的基于反射的编程模式。
读前必备:
[.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)
1.什么是.NET反射?
反射是.NET一个重要的特性,《CLR via C#》一书中对.NET反射的解释为:在我们应用程序中使用元数据来表示存储。编译程序集或模块时,编译器会创建一个类型定义表、一个字段定义表、一个方法定义表以及其它表。而我们如果想动态调用这些元数据表(或说是解析这些表),或说是为这些元数据创建一个对象模型,这个过程就是反射。
简单通俗的说,就是动态调用编译过的程序集中的属性,字段,方法等的过程,就是反射。
反射在.NET,通过System.Reflection命名空间中的类来实现。
2.反射能为我们做些什么?
这个问题是我们学习反射的重点,总得知道学习它的好处,才会继续把本文看下去。
反射特性,确实是.NET一个非常重要且有用的特性。
A.枚举类型成员
B.实例化新对象
C.执行对象成员
D.查找类型信息
E.查询程序集信息
F.检查应用于某种类型的自定义特性
G.创建和编译新的程序集
H.简化执行时而非编译时绑定的数据的操作。(C# 4.0以后新功能)
此外.NET新版本中允许泛型上的反射.
以上是反射的基本特性,参考了《C#本质论》和《C#高级编程》
基于上面的基本特性,我们可以设计出很多非常实用的编程模式。
下面列举几种基于反射设计模式下的实例:
A.利用反射创动态创建程序集的API文档。基于反射允许枚举程序集中类型及成员的特性,我们可以通过反射获取已编译的程序集中的字段方法属性事件和他们的XML注释。从而动态创建程序集的API文档;
B.非常常用的反射工厂模式。反射工厂模式在设计模式中比较容易理解,也比较简单。很多代码生成器中就利用这种设计模式完成不同数据库的反射调用。比如我们有MsSql、MySql、Oracle这三种数据库,在项目设计中,我们有可能随时换另一种数据库(当然这只是假设),因此需要同时实现这三种数据库的基础增删改查的类即数据访问类。我们要切换数据库的时候,只需要在config中更改数据库类型,其他的工作交给反射工厂类去动态调用编译好的程序集中对应的数据库访问方法。
如果没有理解也没关系,这里只是说明一下反射的应用实例,以便于更有信心的学习反射。反射在设计模式中的应还有很多,这里不再列举。
3.反射应用基础
上面说了这么多,无非就是先让我们理解反射能为我们做些什么,下面进入正题,说一下反射的代码实现。
下面主要介绍反射的核心类及类成员
反射的命名空间:System.Reflection
反射的类大多都在这个命名空间中。
主要的类: System.Type
这个类是反射的核心,其属性方法可以得到运行时的信息。
Type类派生于System.Reflection.MemberInfo抽象类
|
MemberInfo类中的只读属性 |
||
|
属性 |
描述 |
备注 |
|
Type DeclaringType |
获取声明该成员的类或接口的类型 |
|
|
MemberTypes MemberType |
获取成员的类型,这个值用于指示该成员是字段、方法、属性、事件、或构造函数 |
这是一个枚举,它定义了用于表示不同成员的类型值。这些值包括:MemberTypes.Constructor, MemberTypes.Method, MemberTypes.Field, MemberTypes.Event, MemberTypes.Property。因此可以通过检查MemberType属性来确定成员的类型,例如,在MemberType属性的值为MemberTypes.Method时,该成员为方法 |
|
Int MetadataToken |
获取与特定元数据相关的值 |
|
|
Module Module |
获取一个代表反射类型所在模块(可执行文件)的Module对象 |
|
|
String Name |
成员的名称 |
|
|
Type ReflectedType |
反射的对象类型 |
|
|
Type类的只读属性 |
|
|
属性 |
描述 |
|
Assembly Assembly |
获取指定类型的程序集 |
|
TypeAttributes Attributes |
获取制定类型的特性 |
|
Type BaseType |
获取指定类型的直接基类型 |
|
String FullName |
获取指定类型的全名 |
|
bool IsAbstract |
如果指定类型是抽象类型,返回true |
|
bool IsClass |
如果指定类型是类,返回true |
|
string Namespace |
获取指定类型的命名空间 |
|
Type类的方法 |
|
|
方法 |
描述 |
|
ConstructorInfo[] GetConstructors() |
获取指定类型的构造函数列表 |
|
EventInfo[] GetEvents(); |
获取指定类型的时间列 |
|
FieldInfo[] GetFields(); |
获取指定类型的字段列 |
|
Type[] GetGenericArguments(); |
获取与已构造的泛型类型绑定的类型参数列表,如果指定类型的泛型类型定义,则获得类型形参。对于正早构造的类型,该列表就可能同时包含类型实参和类型形 |
|
MethodInfo[] GetMethods(); |
获取指定类型的方法列表 |
|
PropertyInfo[] GetProperties(); |
获取指定类型的属性列表e |
|
MemberInfo[] GetMembers(); |
获取指定类型的成员列表 |
反射还有很多类,这里不一一介绍,详细可以查阅MSDN:
https://msdn.microsoft.com/zh-cn/library/system.reflection.aspx
4.反射实例
下面通过一个实例来学习一下反射最基本的使用方法。
建立一个解决方案,包含两个项目,项目ClassLibrary生成一个DLL(包含两个类),另一个项目是ReflectionTestGet,用于反射调用类ClassLibrary

第一个项目的两个类如下:
MartialArtsMaster.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ClassLibrary
{
/// <summary>
/// 类:武林高手
/// MartialArtsMaster
/// </summary>
class MartialArtsMaster
{
/// <summary>
/// 级别
/// </summary>
public int _level = ;
/// <summary>
/// 编号
/// </summary>
public int Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
/// <summary>
/// 门派
/// </summary>
public string Menpai { get; set; }
/// <summary>
/// 武学
/// </summary>
public string Kungfu { get; set; }
/// <summary>
/// 级别
/// </summary>
public int Level
{
get
{
return _level;
} set
{
_level = value;
}
} /// <summary>
/// 攻击
/// </summary>
/// <param name="kungfu"></param>
/// <returns></returns>
public string Attack(string kungfu)
{
return "使用用了功夫:" + kungfu;
} public string Kill(string kungfu, string name)
{
return "使用用了功夫:" + kungfu + "击杀了" + name;
}
}
}
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ClassLibrary
{
/// <summary>
/// 类:人
/// </summary>
class Person
{
public string gender { get; set; }
public string race { get; set; }
public string Country { get; set; }
public string Eat(string strCountry)
{
switch (strCountry)
{
case "美国": return "爱吃西餐"; case "韩国": return "爱吃泡菜";
default:
return "不知道";
}
}
}
}
第二个项目调用如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection; namespace ReflectionTestGet
{
class Program
{
static void Main(string[] args)
{ Assembly asm = Assembly.LoadFrom("ClassLibrary.dll"); //加载指定的程序集
Type[] alltype = asm.GetTypes(); //获取程序集中的所有类型列表
foreach (Type calssName in alltype)
{
Console.WriteLine("加载程序的集类名:"+ calssName.Name); //打印出程序集所有类
foreach (var field in calssName.GetFields())
Console.WriteLine(calssName.Name+"字段有:" + field.Name); //打印出程序集所有字段,注意只能获取公有字段
foreach (var pro in calssName.GetProperties())
Console.WriteLine(calssName.Name + "属性有:" + pro.Name); //打印出程序集所有属性
foreach (var met in calssName.GetMethods())
Console.WriteLine(calssName.Name + "方法有:" + met.Name); //打印出程序集所有方法 }
Console.ReadKey();
}
}
}
运行结果如下:

5.本节要点:
本节主要介绍和反射的用途及反射的基本操作类及属性方法,下节继续深入介绍如何将反射技术应用于实际项目之中。
==============================================================================================
<如果对你有帮助,记得点一下推荐哦,如有
有不明白或错误之处,请多交流>
<对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>
<转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>
.NET 技术交流群:467189533 
==============================================================================================
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程的更多相关文章
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
[.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...
- [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)
[.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...
- [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能
[.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...
- [.net 面向对象程序设计进阶] (14) 缓存(Cache) (一) 认识缓存技术
[.net 面向对象程序设计进阶] (14) 缓存(Cache)(一) 认识缓存技术 本节导读: 缓存(Cache)是一种用空间换时间的技术,在.NET程序设计中合理利用,可以极大的提高程序的运行效率 ...
- [.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中)
[.net 面向对象程序设计进阶] (17) 多线程(Multithreading)(二) 利用多线程提高程序性能(中) 本节要点: 上节介绍了多线程的基本使用方法和基本应用示例,本节深入介绍.NET ...
- [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦
[.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...
- [.net 面向对象程序设计进阶] (1) 开篇
[.net 面向对象程序设计进阶] (1) 开篇 上一系列文章<.net 面向对象编程基础>写完后,很多小伙伴们希望我有时间再写一点进阶的文章,于是有了这个系列文章.这一系列的文章中, 对 ...
- [.net 面向对象程序设计进阶] (23) 团队开发利器(二)优秀的版本控制工具SVN(上)
[.net 面向对象程序设计进阶] (23) 团队开发利器(二)优秀的版本控制工具SVN(上) 本篇导读: 上篇介绍了常用的代码管理工具VSS,看了一下评论,很多同学深恶痛绝,有的甚至因为公司使用VS ...
- [.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下)
[.net 面向对象程序设计进阶] (24) 团队开发利器(三)使用SVN多分支并行开发(下) 本篇导读: 接上篇继续介绍SVN的高级功能,即使用分支并行开发.随着需求的不断变更,新功能的增加.特别是 ...
随机推荐
- Denormalization 2
In a relational database, denormalization is an approach to speeding up read performance (data retri ...
- Windows8 UI MessageBox In DevExpress
// custom messagebox using System; using System.Drawing; using System.Windows.Forms; using DevExpres ...
- NXP恩智浦P89V51RB2/RC2/RD2单片机解密芯片破解方法!
NXP恩智浦P89V51RB2/RC2/RD2单片机解密芯片破解 P89V51RB2/RC2/RD2是一款80C51微控制器,包含16/32/64kB Flash和1024字节的数据RAM. P89V ...
- locky勒索样本分析
前段时间收到locky样本,分析之后遂做一个分析. 样本如下所示,一般locky勒索的先决条件是一个js的脚本,脚本经过了复杂的混淆,主要用于下载该样本文件并运行,. 解密 样本本身进行了保护,通过i ...
- OpenCV2.4.13+VS2013开发环境配置
List1:完成 写在前面:之前电脑很杂乱的装了OpenCV的2个版本,在配置OpenCV和VS2013环境时死活配不好.但是接下来的工作要用到,没有办法,还是得好好做.今天重新装了OpenCV2.4 ...
- 利用DNS Zone Transfers漏洞工具dnswalk
利用DNS Zone Transfers漏洞工具dnswalk DNS Zone Transfers(DNS区域传输)是指一台备用服务器使用来自主服务器的数据刷新自己的域(zone)数据库.当主服 ...
- C++模板分离
在正常情况下,c++模板是不允许在头文件声明,在cpp文件中实现.那是因为在cpp文件在编译时内存必须要给它分配储存空间.但是模板本身是一种泛型,在没有明确定义声明类型前,编译器也无法知道它的大小.所 ...
- HDU5909 Tree Cutting(树形DP + FWT)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5909 Description Byteasar has a tree T with n ve ...
- 【转】查询oracle比较慢的session和sql
-查询最慢的sql select * from ( select parsing_user_id,executions,sorts command_type,disk_reads,sql_text f ...
- [译]App Framework 2.1 (1)之 Quickstart
最近有移动App项目,选择了 Hybrid 的框架Cordova 和 App Framework 框架开发. 本来应该从配置循序渐进开始写的,但由于上班时间太忙,这段时间抽不出空来,只能根据心情和 ...