.Net中的反射使用入门

timmy3310 2003-09-02 11:13:12
我又来了。
这次讲反射的原因,是因为上午答了一个帖子,是关于反射的,发现里面很多人对反射、类型、装配件这些概念都还不了解,甚至有错误的了解,我的正确答案居然只有qqchen才认为是正确的,看来是有必要普及一下这方面的知识了。


MSDN:
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpcondiscoveringtypeinformationatruntime.htm
提纲:
1、 什么是反射
2、 命名空间与装配件的关系
3、 运行期得到类型信息有什么用
4、 如何使用反射获取类型
5、 如何根据类型来动态创建对象
6、 如何获取方法以及动态调用方法
7、 动态创建委托



1、什么是反射
Reflection,中文翻译为反射。
这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:

Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。
MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。
诸如此类,还有FieldInfo、EventInfo等等,这些类都包含在System.Reflection命名空间下。

2、命名空间与装配件的关系
很多人对这个概念可能还是很不清晰,对于合格的.Net程序员,有必要对这点进行澄清。
命名空间类似与Java的包,但又不完全等同,因为Java的包必须按照目录结构来放置,命名空间则不需要。

装配件是.Net应用程序执行的最小单位,编译出来的.dll、.exe都是装配件。

装配件和命名空间的关系不是一一对应,也不互相包含,一个装配件里面可以有多个命名空间,一个命名空间也可以在多个装配件中存在,这样说可能有点模糊,举个例子:
装配件A:
namespace N1
{
public class AC1 {…}
public class AC2 {…}
}
namespace N2
{
public class AC3 {…}
public class AC4{…}
}
装配件B:
namespace N1
{
public class BC1 {…}
public class BC2 {…}
}
namespace N2
{
public class BC3 {…}
public class BC4{…}
}

这两个装配件中都有N1和N2两个命名空间,而且各声明了两个类,这样是完全可以的,然后我们在一个应用程序中引用装配件A,那么在这个应用程序中,我们能看到N1下面的类为AC1和AC2,N2下面的类为AC3和AC4。
接着我们去掉对A的引用,加上对B的引用,那么我们在这个应用程序下能看到的N1下面的类变成了BC1和BC2,N2下面也一样。
如果我们同时引用这两个装配件,那么N1下面我们就能看到四个类:AC1、AC2、BC1和BC2。

到这里,我们可以清楚一个概念了,命名空间只是说明一个类型是那个族的,比如有人是汉族、有人是回族;而装配件表明一个类型住在哪里,比如有人住在北京、有人住在上海;那么北京有汉族人,也有回族人,上海有汉族人,也有回族人,这是不矛盾的。

上面我们说了,装配件是一个类型居住的地方,那么在一个程序中要使用一个类,就必须告诉编译器这个类住在哪儿,编译器才能找到它,也就是说必须引用该装配件。
那么如果在编写程序的时候,也许不确定这个类在哪里,仅仅只是知道它的名称,就不能使用了吗?答案是可以,这就是反射了,就是在程序运行的时候提供该类型的地址,而去找到它。
有兴趣的话,接着往下看吧。

3、运行期得到类型信息有什么用
有人也许疑问,既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响。
这就是个见仁见智的问题了,就跟早绑定和晚绑定一样,应用到不同的场合。有的人反对晚绑定,理由是损耗效率,但是很多人在享受虚函数带来的好处的时侯还没有意识到他已经用上了晚绑定。这个问题说开去,不是三言两语能讲清楚的,所以就点到为止了。
我的看法是,晚绑定能够带来很多设计上的便利,合适的使用能够大大提高程序的复用性和灵活性,但是任何东西都有两面性,使用的时侯,需要再三衡量。

接着说,运行期得到类型信息到底有什么用呢?
还是举个例子来说明,很多软件开发者喜欢在自己的软件中留下一些接口,其他人可以编写一些插件来扩充软件的功能,比如我有一个媒体播放器,我希望以后可以很方便的扩展识别的格式,那么我声明一个接口:
public interface IMediaFormat
{
string Extension {get;}
Decoder GetDecoder();
}
这个接口中包含一个Extension属性,这个属性返回支持的扩展名,另一个方法返回一个解码器的对象(这里我假设了一个Decoder的类,这个类提供把文件流解码的功能,扩展插件可以派生之),通过解码器对象我就可以解释文件流。
那么我规定所有的解码插件都必须派生一个解码器,并且实现这个接口,在GetDecoder方法中返回解码器对象,并且将其类型的名称配置到我的配置文件里面。
这样的话,我就不需要在开发播放器的时侯知道将来扩展的格式的类型,只需要从配置文件中获取现在所有解码器的类型名称,而动态的创建媒体格式的对象,将其转换为IMediaFormat接口来使用。

这就是一个反射的典型应用。
...全文
1540 156 打赏 收藏 转发到动态 举报
写回复
用AI写文章
156 条回复
切换为时间正序
请发表友善的回复…
发表回复
IamRobert 2004-03-12
  • 打赏
  • 举报
回复
反射
hygui 2004-03-11
  • 打赏
  • 举报
回复
完全不懂
收藏先
jiezhi 2004-03-11
  • 打赏
  • 举报
回复
up
yzh0523 2004-03-11
  • 打赏
  • 举报
回复
谢谢!!!收藏
hawkeyes_yq 2004-03-11
  • 打赏
  • 举报
回复
太好了!正在学习..........!
Jinniu 2004-03-11
  • 打赏
  • 举报
回复
学习
wiselyjs 2004-03-11
  • 打赏
  • 举报
回复
收藏!
chinanewway 2004-03-11
  • 打赏
  • 举报
回复
收藏
tonghua990613 2004-03-11
  • 打赏
  • 举报
回复
学习
yangzhenhai 2004-03-11
  • 打赏
  • 举报
回复
收藏
zxhywsl 2004-03-11
  • 打赏
  • 举报
回复
太好了,学习,收藏
mousetrue 2004-03-11
  • 打赏
  • 举报
回复
顶。。。真是好贴子。。这个问题已经困了我好久了。。。就是找不到答案。。
Wuzhou98 2004-03-01
  • 打赏
  • 举报
回复
gz
CYG369 2004-03-01
  • 打赏
  • 举报
回复
up
clipper_clipper 2004-03-01
  • 打赏
  • 举报
回复
UP T00
brightheroes 2004-02-19
  • 打赏
  • 举报
回复
我晕
怎么这么老早的帖子都翻出来了

不过这个帖子的确强
SailorDreamer 2004-02-19
  • 打赏
  • 举报
回复
学习,
以前只用过
System.Reflection.Missing.Value
lovered 2004-02-19
  • 打赏
  • 举报
回复
好多回复啊

[2004-2-19](天啊都2004年了)签名:
我要让C#论坛中充满我的名字,哈哈哈哈哈哈哈
hpretty 2004-02-19
  • 打赏
  • 举报
回复
楼上说的是用到另外一个类了

System.Convert.ChangeType()
winapp 2004-02-19
  • 打赏
  • 举报
回复
用Type、MethodInfo可以取得类信息和方法信息,可是我还是不明白怎么实现动态调用。
因为不明白方法的参数信息ParameterInfo[]怎么动态使用。虽然MethodInfo可以取得参数信息,但是怎么用呢?调用者是不知道参数类型的,知道的最多是参数个数,它可以提供参数,很可能全部用string类型的。我该怎么根据MethodInfo.GetParameters()取得的参数信息把STRING类型的参数全部转换成所需参数啊?如果我不能转换,动态调用岂不是一句空话?
加载更多回复(136)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧