先看段代码:
Interface IMedia
{
Void Play();
Void Stop();
}
Public class Radio : IMedia
{
Void Play();{….}
Void Stop();{….}
}
Public class Recorder;: IMedia
{
Void Play();{….}
Void Stop();{….}
}
Public class MediaFactory
{
//取得所有播放设备
Public string[] GetDevicelst() {return new string[]{“Radio”,” Recorder”};
Public IMedia CreateDevice(string DeviceName)
{
If (DeviceName== “Radio”)
rturn new Radio();
else if (DeviceName== “Recorder”)
rturn new Recorder ();
elser
return null;
}
}
可见页面:
这段代码想必都很熟悉,这就不是个工厂模式么,没错,是个典型的工厂模式,而且还知道不少优点:
1. 采用了接口方式,统一使用IMedia来调用,而不会直接使用Radio或Recorder,省了不少代码,不再需要很多重复代码了;
2. 可以方便的扩展啊,比如我再新增一种播放设备的话,只要新增一个类,然后在MediaFactory中加上相应的代码就可以了啊,这对于使用者来说,可以不用修改代码了。
方便,确实方便很多了,但仔细想来啊,又有麻烦了,前面的程序已经开发好了,我要再加一个播放设备,加一个类的话,还得打开原先的代码,加上这个类,然后再MediaFactory中加上创建便个新类的方法,然后再编译后才能使用。
能不能简化呢,能不能我这个新的播放类,单独写一下,放到一个新的dll中,然后把这个dll往原先的exe目录中一放,然后就可以调用到这个新的播放类呢,这样我就可以不动原先的程序了呢?
答案是可以的:
Public string[] GetDevicelst() {return new string[]{“Radio”,” Recorder”};
看到这段代码,我们想到了,这个字符串不就可以保存在配置文件中吧,好,改之:
Public string[] GetDevicelst() {return Settings.Devicelist.Split(‘;’);}
在配置文件(exe.config)中:
<userSettings>
<WindowsFormsApplication1.Properties.Settings>
<setting name=" Devicelist " serializeAs="String">
<value> Radio ; Recorder </value>
</setting>
</WindowsFormsApplication1.Properties.Settings>
</userSettings>
好,取得设备列表的动态生成搞定了,新增一个类,也只要在这个配置文件里面加个,但看第二个方法CreateDevice,犯难了,在配置文件里面我保存的是类名的字符串,而在这个方法里面得返回其实例,得用new 类名()来创建对象。
这里我们在想是不是有这样一个方法,object instance = CreateInstance(“类名”),这样通过一个字符串,系统就给我返回相应的对象实例。
答案是有的,有这样的方法,这就是反射,我们看下怎么来用。
我们知道,在C#里面类型是随便取的,也就是就可以让两个类型相同,只不过在同一个程序里面,这两个相同的类得用不同的命空间里,在同一程序里,要表达一个类,得用命名空间.类名来表示。
但是在不同的dll中,还是会出现相同的命名空间和类名,所以对于全局来讲,要唯一表过一个类的话,得这样写命名空间.类名,程序集名。一般来说,这要样肯定也就够了,但时,不难保证,我的dll名称也可能相同啊,哦好,加个版本吧:命名空间.类名,程序集名, Version=版本号,那对于.net来说,还有一个多国语言支持呢,我同一批程序同一个版本,不同国家语言的包也可以相同啊,哦好,再加个语言限定吧:命名空间.类名,程序集名, Version=版本号, Culture=neutral这里面的neutral表示本地化的,就是自动读取操作系统的语言。如果再有相同的怎么办呢,没关系,我们可以在这个程序集上加一个guid啊,这个叫做强签名,这样,这个dll中的类就完全唯一了:命名空间.类名,程序集名, Version=版本号, Culture=neutral, PublicKeyToken=null/Guid值。OK,这就是一个类的全名的表示法,当然可以简写,”命名空间.类名,程序集名”,只要系统中没发现重复的就没事,发现重复的就要报错了的哦。
既然每个类可以用这个长长的字符串来定义的话,在framework中,就有这样一个表示类的类,叫做Type,每一个Type实例都唯一对应着一个类,那么Type对象怎么获取呢,肯定只有在dll(程序集)中找咯,又有一个对象Assembly,这个类是专门来表示程序集的,在这个Assembly中,有一个方法GetTypes,返回这个dll中的所有Type的集合。有了Type对象后就可很方便地创建其实例咯:
Assembly assembly = Assembly.LoadFile("xxxx.dll");
Type type = assembly.GetType("Radio");
object instance = Activator.CreateInstance(type); //创建实例
IMedia media = instance as IMedia;
这下好办了,可以能过字符串来取得对象了,好,将前面的代码改造下,连原来的配置文件都不要了:
Public class MediaFactory
{
//取得所有播放设备, 用hash表记录所有的设备列表,<名称,类型>
Public Hashtable GetDevicelst() {
Hashtable rtn = new Hashtable();
foreach (string file in Directory.GetFiles(Application.ExecutablePath, "*.dll"))
{
Assembly assembly = Assembly.LoadFile("xxxx.dll");
foreach (Type type in assembly.GetTypes())
{
//判断type是否继承IMedia
rtn.Add(type.Name, typ)
}
}
return rtn;
}
public IMedia CreateDevice(Type type)
{
Type type = assembly.GetType("Radio");
object instance = Activator.CreateInstance(type); //创建实例
return instance as IMedia;
}
}
看明白这段代码了吧,这样就实现了前面的要求,丢个dll到exe下面,就可以认出里面的IMedia类来并可调用了。
既然可以通过字符串来找到程序集,找到里面的类,还能创建具体的实例,那能不能继续,查找到类里有几个函数,有几个属性,然后能否再动态取得你这们实例里面的某个属性值,动态调用类里面的方法呢:
type.GetProperties();
type.GetMethods();
PropertyInfo prop;
prop.GetValue(obj);
MethodInfo method;
method.Invoke(obj, 参数);
看吧,这些方法够你遐想了,尽情地用到你可以简化代码的地方法吧!
反射,在类里面,反过来动态(运行时)找找类本身内部有哪些方法属性等结构!
分享到:
相关推荐
在Java中,反射是一种机制,它允许程序在运行时获取和操作类的信息,包括类的构造器、字段、方法等。通过反射,我们可以在编译时期未知类的情况下,动态地操作类的成员。
是关于c#的一个反射举例,希望大家对C#的反射能够一个很好的认识,帮助大家更请简单的理解其中的意思
NULL 博文链接:https://stephen830.iteye.com/blog/256723
温习java反射,让你对反射有全新的认识(csdn)————程序
java反射技术应用的很广泛,多看源码,对理解java反射的理解会有很好的认识,这个源码有我自己的理解在里边
从重新认识反射的定义开始,了解JAVA的核心技术; 理解Java中9大内置Class实例; 详细介绍包名、类名、接口、继承、修饰符等内容; 深入理解List、Map、Set的实现机制以及原理 深入理解泛型的原理以及在日常工作...
从反射系数颜色和概率分布函数两方面对实际测井数据反射系数序列进行试验分析,得出实际反射系数的振幅谱趋于蓝色、概率密度趋于非高斯随机分布的基本认识。基于试验分析的结果,利用测井数据拟合描述反射系数颜色的两...
除了能测量光强外,还能利用光线投射、遮挡、反射、干涉等测量多种物理量,如尺寸、位移、速度、温度等。 任务一 认识光电传感器 2.红外热释电探测器 主要是利用辐射的红外光(热)照射材料时引起材料电学性质发生...
瞬变电磁对富水低阻体敏感,地震反射波对隐伏地质构造响应明显。两者联合使用不仅能够探明构造异常与含水异常,还可进一步分析地质异常的类别,提高了地质超前探的精度与认识,更便于精确地指导巷道安全掘进。
本篇主要是深入对Java中的Class对象进行分析,这对后续深入理解反射技术非常重要,主要内容如下:认识Class对象之前,先来了解一个概念,RTTI(Run-TimeTypeIdentification)运行时类型识别,对于这个词一直是C++中...
但主力煤层地震反射资料信噪比低、剖面成像效果差,制约了该区煤层气勘探开发工作。工区内灰岩大面积裸露、目的层埋藏浅是导致该区地震资料信噪比低的最主要因素。实践表明:基于数字盒子波调查的模拟检波器多道组合...
1 JAVA认识 2 JAVA数据类型 3 面向对象程序设计 4 JAVA集合 5 JAVA反射机制 6 JAVA注解(ANNOTATION) 7 JAVA中的异常类 8 JAVA-SWING 9 观察者模式 10 内部类讲解 11 JAVA I/O流讲解 12 JAVA多线程 13 ...
发生器反射 发电机 入门 什么是Yeoman? 技巧问题。 没关系是这个人: 基本上,他戴着顶帽子,住在您的计算机中,然后等待您告诉他您希望创建哪种应用程序。 并非每台新计算机都预装了Yeoman。 他住在软件包存储...
讲解格雷码之前,首先了解一下格雷码的定义: • 对数据编码后,若任意两个相邻的码值间只有一位二进制数不同,则称这种编码为格雷...• 由于最大数与最小数之间也仅只有一位数不同,即首尾相连,又称循环码或反射码。
为了深化对其的认识,通过几何光学和物理光学的方法,对离轴90°抛物面镜应用于激光聚焦光路时,光轴的角度失准对聚焦光斑造成的影响进行分析。结果表明,细微的角度失准将导致焦斑面积大大增加,从而大大降低了焦斑的...
煤矿巷道顶板树脂锚杆锚固质量应力波法无损检测的实质在于准确测试并分析应力波的传播特性,目前对锚固体中应力波传播特性的认识并不全面。本文数值计算不同围岩类型、不同岩层组合、不同密实度、不同工作载荷锚固体...
我以为Rust没有反射……?...这个想法是,我们公开看起来像无聊的简单的API,例如,您可能认识到是使用了还是使用了。 宏作者使用该类型的API来表达其宏的逻辑,使用诸如reflect::Value类的类型来检索函