一、MSDN上面找的学习资料
反射提供了封装程序集、模块和类型的对象( 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
反射通常具有以下用途:
· 使用 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。
· 使用 了解如下的类似信息:包含模块的程序集以及模块中的类等。您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
· 使用 了解以下信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 的 或 方法来调用特定的构造函数。
· 使用 了解以下信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 的 或 方法来调用特定的方法。
· 使用 了解以下信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。
· 使用 来了解如下的类似信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。
· 使用 来了解如下的类似信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。
· 使用 来了解如下的类似信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。
· 当您在一个应用程序域的仅反射上下文中工作时,请使用 来了解有关自定义属性的信息。使用 CustomAttributeData,您不必创建属性的实例就可以检查它们。
二、反射的重要应用与相关练习
反射在下列情况下很有用:
· 需要访问程序元数据的属性。
C# 具有一个反射系统,可用来检索用自定义属性定义的信息。主要方法是 GetCustomAttributes,它返回对象数组,这些对象在运行时等效于源代码属性。
下面是我参照MSDN写的一个例子:定义一个自定义属性,将其应用于若干实体并通过反射进行检索。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Attribut 6 { 7 //允许指定多个属性实例,类YaoJian中进行了练习 8 [AttributeUsage(AttributeTargets.Class,AllowMultiple = true)] 9 public class Students:Attribute10 { 11 string name;12 public int age;13 14 public Students(string Name)15 { 16 name = Name;17 age = 18;18 }1920 public string GetName()21 { 22 return name;23 }24 }25 //将自定义属性应用于类26 [Students("李江")]27 class LiJiang28 { 29 //30 }3132 //不定义Students属性33 class ZhaoYong34 { 35 //36 }37 //应用多个属性实例38 [Students("姚键"),Students("李云",age = 20)]39 class YaoJian40 { 41 //42 }43 class Program44 { 45 static void Main(string[] args)46 { 47 StudentsInfo(typeof(LiJiang));48 StudentsInfo(typeof(ZhaoYong));49 StudentsInfo(typeof(YaoJian));50 }5152 private static void StudentsInfo(Type t)53 { 54 Console.WriteLine("学生信息是:{0}",t);55 //获取对象中的自定义属性56 Attribute[] att = Attribute.GetCustomAttributes(t);57 foreach (Attribute a in att)58 { 59 if (a is Students)60 { 61 Students S = (Students)a;62 Console.WriteLine("学生的姓名是:{0},年龄是:{1}",S.GetName(),S.age.ToString());63 }64 }65 }66 }67} 68 运行结果是: · 检查和实例化程序集中的类型。
· 在运行时构建新类型。使用
中的类。 · 执行后期绑定,访问在运行时创建的类型的方法。
三、实践,用反射调用COM
用反射调用COM非常的方便,不需要先对COM进行注册添加引用,用Assembly类中的LoadFrom方法直接可以讲.dll文件加载到程序中,然后对其实例化使用。
实例:
1、先做一个简单的调用系统outlook的COM。
先在 VS2005 中建一个 windows 控件库工程,取名为 Send ,然后把控件的界面删掉,在 Send 工程中添加一个 windows 窗体也取名为 Send ,在窗体的 load 事件里面写代码调用 outlook 。完整的代码如下: 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 // 使用进程引用命名空间 10 using System.Diagnostics; 11 namespace Send 12 { 13 public partial class Send : Form14 { 15 public Send()16 { 17 InitializeComponent();18 }19 /**//// <summary>20 /// 在Form_Load中调用Windows带的outlook21 /// </summary>22 /// <param name="sender"></param>23 /// <param name="e"></param>24 private void Send_Load(object sender, EventArgs e)25 { 26 Process P = new Process();27 P.StartInfo.FileName = "C:\\Program Files\\Outlook Express\\msimn.exe";28 P.Start();29 this.Close();30 }31 }32} 33 代码写完以后,生成一下,这时在工程的bin文件夹下面就生成了一个Send.dll的文件。
2、用反射来调用上面的COM
在Send工程的解决方案上面点击右键添加/新建项目/windows应用程序,取名Fanshe在Form1上面添加一个button,并设置其相关属性,界面如图:把上面生成的Send.dll放到Fanshe的bin目录下面,在button的click事件中添加代码调用COM,完整代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 // 使用反射引用的命名空间 10 using System.Reflection; 11 12 namespace Fanshe 13 { 14 public partial class frm : Form15 { 16 public frm()17 { 18 InitializeComponent();19 }2021 private void btn_Click(object sender, EventArgs e)22 { 23 /**//*加载COM,这样写COM的默认路径在bin文件夹下,如果不在可以通过绝对路径或者相对路径指到COM所在的位置24 *比如:Assembly.LoadFrom("D://App//Send.dll")或Assembly.LoadFrom(".//Send.dll")25 */26 Assembly A = Assembly.LoadFrom("Send.dll");27 //注意参数中,第一个Send是COM中要实例化类的命名空间名,第二个Send是类名28 Object O = A.CreateInstance("Send.Send");29 Form F = (Form)O;30 F.Show();31 }32 }33} 34 代码完成后,将 Fanshe 设为启动项并运行,点击 button ,调出 outlook ,界面如下: 这个简单的例子就完成了,里面使用了反射的很少一部分内容,但也可以帮助理解反射机制。
四、反射的应用要点
1.现实应用程序中很少有应用程序需要使用反射类型
2.使用反射动态绑定需要牺牲性能
反射的性能损失主要来源于比较类型、遍历成员、调用成员三种情形,其中比较类型耗时最小,调用成员耗时最多,所以尽量减少采用成员动态调用等反射方式可以提高应用程序性能。除此之外,采取后期绑定、避免将反射方法放到循环内产生放大效应等办法均可提升反射性能。
3.有些元数据信息是不能通过反射获取的
某些反射类型是专门为那些 clr 开发编译器的开发使用的,所以你要意识到不是所有的反射类型都是适合每个人的。 程序下载: