程序代码在编译后生成可执行的应用,我们首先要了解这种可执行应用程序的结构。
应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域,这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局。
程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途。
(1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
(2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetConstructors或GetConstructor方法来调用特定的构造函数。
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。
(5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
System.Reflection.Emit命名空间的类提供了一种特殊形式的反射,可以在运行时构造类型。
反射也可用于创建称为类型浏览器的应用程序,使用户能够选择类型,然后查看有关选定类型的信息。
此外,Jscript等语言编译器使用反射来构造符号表。System.Runtime.Serialization命名空间中的类使用反射来访问数据并确定要永久保存的字段,System.Runtime.Remoting命名空间中的类通过序列化来间接地使用反射。
实例:
在C#中新建一个类库TestReflect
新建类ReflectText
键入以下代码
public class ReflectText
{
public ReflectText()
{ }
public string WriteString(string s)
{
return "欢迎您," + s;
}
public static string WriteName(string s, string k)
{
return "欢迎光临," + s + "ni hao " + k;
}
public string WriteNoPara()
{
return "您使用的是无参数方法";
}
}
在新建一个"Web应用程序",并将TestReflect.dll导入
在Main函数中键入以下代码(这是就可以调试了享受一下反射带来的乐趣,在总结一下反射会用在那些场合就可以了)
Code
protected void Page_Load(object sender, EventArgs e)
{
System.Reflection.Assembly ass;
Type type;
object obj;
try
{
ass = System.Reflection.Assembly.LoadFile(@"C:/Documents and Settings/Administrator/桌面/TestReflect/TestReflect/bin/Debug/TestReflect.dll");
//ass = System.Reflection.Assembly.Load(@"C:/Documents and Settings/Administrator/桌面/html/TestReflect/TestReflect/bin/Debug/TestReflect.dll");
type = ass.GetType("Webtest.ReflectText");
System.Reflection.MethodInfo method = type.GetMethod("WriteString");
obj = ass.CreateInstance("Webtest.ReflectText");
string s = (string)method.Invoke(obj, new string[] { "齐天大圣" });
Response.Write(s + "
");
method = type.GetMethod("WriteNoPara");
s = (string)method.Invoke(obj, null);
Response.Write(s + "
");
method = type.GetMethod("WriteName");
s = (string)method.Invoke(obj, new string[] { "dasha","shage"});
Response.Write(s + "
");
Type[] paramTypes = new Type[2];
paramTypes[0] = System.Type.GetType("System.Double");
paramTypes[1] = System.Type.GetType("System.Double");
MethodInfo med = type.GetMethod("WriteName", paramTypes);
object[] parameters = new object[2];
parameters[0] = "中国";
parameters[1] = "日本";
s = (string)method.Invoke(obj,parameters);
Response.Write(s + "
");
method = null;
}
catch (Exception ex)
{
Response.Write(ex + "
");
}
finally
{
ass = null;
type = null;
obj = null;
}
}
}
反射的作用:(Copy From Somewhere)
1. 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型
2. 应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射。
3. 反射主要应用与类库,这些类库需要知道一个类型的定义,以便提供更多的功能。