C#基础知识回顾-- 反射(4)
从程序集获得类型
先说点题外话,现在技术真的发展太快了。我这边还很多东西半生不熟
呢,那边又出现了好多有趣的新东西让你眼红不已。学还是不学这还真是
个问题。Node.js 、bootstrap,我最近刚发现的新技术,其实他们已经
存在很久了,只是没有接触过而已。昨天晚上看Node.js一下子看到两点
多,感觉真是太有意思了^,有兴趣的可以去看看,大家多交流交流.
好了不废话了,在前面的示例中,几乎全部的MyClass信息都是通过反射得到的,但是有一个例外:
MyClass类型本身。虽然前面的示例可以动态确定MyClass的信息,但它们仍基于以下事实:事先知道
类型名MyClass,并且在typeof语句中使用它创建一个Type对象。尽管这种方式可能在很多环境中都有
用,但是要发挥反射的全部功能,就必须能通过分析其他程序集的内容动态的获取可用的类型。
程序集提供了它包含的类和结构的信息。借助反射应用程序接口,可以加载程序集,获取它的相
关信息并创建其公共可用类型的实例。通过使用这种机制,程序能够搜素其环境,利用那些潜在的功能而
无需在编译期间显示的定义他们。由于类型的全部信息都可以被发现,因此不存在反射应用的内在限制。
为了获取程序集的相关信息,首先需要创建一个Assembly对象。Assembly类并没有定义公有的
构造函数,它的对象实例是通过类的一个方法获得的。这里使用的LoadFrom()方法可以加载由文件名
指定的程序集,其形式如下:
static Assembly LoadFrom(string fileName)
一旦获得了Assembly类型的对象,就可以通过调用该对象的GetType()来得到它所定义的类型
。基本形式如下:
Type[] GetTypes()
此方法返回一个数组,它包含了程序集的类型。
为了说明如何获取程序集的类型,我们需要在解决方案中添加一个类库,类库名字为MyClasses,
在类库中添加三个类:MyClass、AnotherClass、Demo。代码如下:
程序集MyClasses代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyClasses { public class MyClass { int x; int y; public MyClass(int i) { Console.WriteLine("一个参数的构造函数:"); x = y = i; } public MyClass(int i, int j) { Console.WriteLine("两个参数构造函数:"); x = i; y = j; Show(); } public int Sum() { return x + y; } public bool IsBetween(int i) { if (x < i && i < y) return true; else return false; } public void Set(int a, int b) { Console.Write("函数:Set(int a, int b)"); x = a; y = b; Show(); } public void Set(double a, double b) { Console.Write("函数:Set(double a, double b)"); x = (int)a; y = (int)b; Show(); } public void Show() { Console.WriteLine("x:{0},y:{1}", x, y); } } public class AnotherClass { string msg; public AnotherClass(string msg) { this.msg = msg; } public void show() { Console.WriteLine(msg); } } public class Demo { public void test() { Console.WriteLine("我是打酱油的!!"); } } }
使用反射代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace Reflection { class Program { static void Main(string[] args) { ReflectAssemblyDemo(); Console.ReadKey(); } static void ReflectAssemblyDemo() { int val; Assembly asm = Assembly.LoadFrom("MyClasses.dll"); Type[] allTypes = asm.GetTypes(); foreach (Type type in allTypes) { Console.WriteLine("程序集中找到类:" + type.Name); } Console.WriteLine(); //使用第一个类 Type t = allTypes[0]; Console.WriteLine("使用类:" + t.Name); //获得构造函数 ConstructorInfo[] ci = t.GetConstructors(); //显示此类中的构造函数 Console.WriteLine("此类中的构造函数有:"); foreach (ConstructorInfo c in ci) { Console.Write(" " + t.Name + " ("); ParameterInfo[] pi = c.GetParameters(); for (int i = 0; i < pi.Length; i++) { Console.Write(pi[i].ParameterType.Name + " " + pi[i].Name); if (i + 1 < pi.Length) Console.Write(","); } Console.WriteLine(")"); } //获取匹配的构造函数 int x; for (x = 0; x < ci.Length; x++) { ParameterInfo[] pi = ci[x].GetParameters(); if (pi.Length == 2) break; } if (ci.Length == x) { Console.WriteLine("没有匹配的构造函数"); return; } else { object[] consargs = new object[2]; consargs[0] = 10; consargs[1] = 20; object reflectOb = ci[x].Invoke(consargs); Console.WriteLine("通过reflectOb调用方法"); Console.WriteLine(); MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { //获得方法参数 ParameterInfo[] pi = m.GetParameters(); if (m.Name.CompareTo("Set") == 0 && pi[0].ParameterType == typeof(int)) { object[] args = new object[2]; args[0] = 9; args[1] = 18; m.Invoke(reflectOb, args); } else if (m.Name.CompareTo("Set") == 0 && pi[0].ParameterType == typeof(double)) { object[] args = new object[2]; args[0] = 1.25; args[1] = 7.5; m.Invoke(reflectOb, args); } else if (m.Name.CompareTo("Sum") == 0) { val = (int)m.Invoke(reflectOb, null); Console.WriteLine("Sum is {0}", val); } else if (m.Name.CompareTo("IsBetween") == 0) { object[] args = new object[1]; args[0] = 13; if ((bool)m.Invoke(reflectOb, args)) { Console.WriteLine("13 is between x and y"); } } else if (m.Name.CompareTo("Show") == 0) { m.Invoke(reflectOb, null); } } } } } }
运行结果:
自此,反射部分基本内容写完了.希望对大家有所帮助.现在正在进行WPF开发,我会把在项目开发中遇到的问题与解决方案及时与您分享,希望您能继续关注.
最后,如果本文对您有所帮助,请点推荐,谢谢!