.NET反射的定义:审查元数据并收集关于它的类型信息的能力。
元数据以非特定语言的方式描述在代码中定义的每一类型和成员。元数据存储以下信息:

.NET反射的概述:
应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域。
这些域在拥有相同应用程序范围的对象周围形成了确定边界。
这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局。
程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。
我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途:
反射也可用于创建称为类型浏览器的应用程序,使用户能够选择类型,然后查看有关选定类型的信息。
此外,Jscript等语言编译器使用反射来构造符号表。System.Runtime.Serialization命名空间中的类使用反射来访问数据并确定要永久保存的字段,System.Runtime.Remoting命名空间中的类通过序列化来间接地使用反射。
反射的性能:
使用反射来调用类型或者触发方法,或者访问一个字段或者属性时clr 需 要做更多的工作:校验参数,检查权限等等,所以速度是非常慢的。
所以尽量不要使用反射进行编程,对于打算编写一个动态构造类型(晚绑定)的应用程序,可以采取以下的几种方式进行代替:
提高反射的性能:反射的性能损失主要来源于比较类型、遍历成员、调用成员三种情形,其中比较类型耗时最小。
调用成员耗时最多,所以尽量减少采用成员动态调用等反射方式可以提高应用程序性能。除此之外,采取后期绑定、避免将反射方法放到循环内产生放大效应等办法均可提升反射性能。
示例如下:这是一个Calculator.dll
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Calculator
{
public interface Iwel
{
string Print();
}
public class Arithmetic:Iwel
{
/// <summary>
/// 实现接口
/// </summary>
/// <returns></returns>
public string Print()
{
return "欢迎使用接口";
}
/// <summary>
/// 没带参数的构造函数
/// </summary>
public Arithmetic()
{
}
/// <summary>
/// 带参数构造函数
/// </summary>
/// <param name="num1"></param>
/// <param name="num2"></param>
public Arithmetic(int num1,int num2)
{
_num1 = num1;
_num2 = num2;
}
private int _num1;
public int Num1
{
get
{
return _num1;
}
set
{
_num1 = value;
}
}
private int _num2;
public int Num2
{
get
{
return _num2;
}
set
{
_num2 = value;
}
}
public string Add(int num1,int num2)
{
Console.WriteLine("{0}+{1}={2}",num1,num2,num1+num2);
return "Add(int num1,int num2)方法是一个共有的带参数的方法";
}
private string Add()
{
return "Add()是一个私有的不传参数的方法";
}
private void Subtration(int num1, int num2)
{
Console.WriteLine("{0}-{1}={2} +Subtration(int num1, int num2)是一个私有带参数的方法",num1,num2,num1-num2);
}
public static void Multiplication(int num1,int num2)
{
Console.WriteLine("{0}+{1}={2} Multiplication(int num1,int num2) 是一个共有的带参数的静态方法",num1,num2,num1*num2);
}
private static void Multiplication()
{
Console.WriteLine("Multiplication()是一个共有不带参数的静态方法");
}
}
}
下面是通过反射检查和调用Calculator.dll中的的方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ReflectionDemo
{
class Program
{
delegate void TestDelegate(int num1,int num2);
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("Calculator"); //加载程序集
Console.WriteLine("得到Calculator.dll中所有的类");
Console.WriteLine("********************************");
foreach(Type t in assembly.GetTypes())
{
Console.WriteLine( "Calculator命名空间下的类:" + t.Name);
}
Console.WriteLine("得到Calculator.dll中所有的模块集");
Console.WriteLine("********************************");
foreach (Module module in assembly.GetModules())
{
Console.WriteLine("Calculator命名空间下的模块:"+module.Name);
}
Console.WriteLine("********************************");
Console.WriteLine("");
//Type type = typeof(Calculator.Arithmetic);
Type type = assembly.CreateInstance("Calculator.Arithmetic").GetType();;
Console.WriteLine("具体的类的类型是" + type.Name);
Console.WriteLine("{0}是不是public类型{1}",type,type.IsPublic);
Console.WriteLine("{0}是不是private类型{1}",type,type.IsNotPublic);
Console.WriteLine("********************************");
Console.WriteLine("");
PropertyInfo[] menberInfo = type.GetProperties();//得到类中的属性
foreach (PropertyInfo p in menberInfo)
{
Console.WriteLine(type + "类的属性有" + p.Name);
}
Console.WriteLine("********************************");
Console.WriteLine("");
Type[] t1 = type.GetInterfaces();
foreach (Type var in t1)
{
Console.WriteLine(var.Name + "Calculator中的接口");
}
Console.WriteLine("********************************");
Console.WriteLine("");
Console.WriteLine("方法的返回类型,方法传参的类型");
//查找私有的方法
MethodInfo[] method = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (MemberInfo var in method)
{
Console.WriteLine("私有的方法:方法名={0} 方法的信息={1}",var.Name,var);
}
//查找公有的方法
MethodInfo[] methodpublic = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach (MethodInfo var in methodpublic)
{
Console.WriteLine("共有的方法: 方法名={0} 方法的信息={1}", var.Name, var);
}
//查找共有的静态方法
MethodInfo[] methodstatic = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach (MethodInfo var in methodstatic)
{
Console.WriteLine("公有静态方法:方法名={0} 方法的信息={1}", var.Name, var);
}
//查找私有的静态方法
MethodInfo[] methdprivatestatic = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static);
foreach (MethodInfo var in methdprivatestatic)
{
Console.WriteLine("私有静态方法:方法名={0} 方法的信息={1}", var.Name, var);
}
Console.WriteLine("********************************");
Console.WriteLine("这是构造方法的形式");
ConstructorInfo[] con = type.GetConstructors(); //获得构造函数的形式
foreach (ConstructorInfo var in con)
{
Console.WriteLine(var);
}
Console.WriteLine("********************************");
object obj = Activator.CreateInstance(type, null); //创建了一个不带参数的实例
//公有非静态带参数和返回参数的方法的调用
MethodInfo men1 = type.GetMethod("Add");
Console.WriteLine("调用{0}方法", men1);
object[] num1 = { 5, 4 };//参数
Console.WriteLine(men1.Invoke(obj, num1));
Console.WriteLine("********************************");
//私有的非静态方法的调用
MethodInfo men2 = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine(men2.Invoke(obj, null));
Console.WriteLine("********************************");
//公有的静态带参数的方法的调用
MethodInfo men3 = type.GetMethod("Multiplication", BindingFlags.Public | BindingFlags.Static);
object[] nums2 = { 5, 6 };
men3.Invoke(null, nums2);
Console.WriteLine("********************************");
//私有的静态的
MethodInfo men4 = type.GetMethod("Multiplication", BindingFlags.NonPublic | BindingFlags.Static);
men4.Invoke(null, null);
Console.WriteLine("********************************");
//动态创建一个委托
Console.WriteLine("动态声明的委托");
TestDelegate dele = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "Subtration");
dele(9, 3);
Console.ReadKey();
}
}
}
执行结果: