元数据以非特定语言的方式描述在代码中定义的每一类型和成员。元数据存储以下信息:
.NET反射的概述:
应用程序结构分为应用程序域—程序集—模块—类型—成员几个层次,公共语言运行库加载器管理应用程序域。
这些域在拥有相同应用程序范围的对象周围形成了确定边界。
这种管理包括将每个程序集加载到相应的应用程序域以及控制每个程序集中类型层次结构的内存布局。
程序集包含模块,而模块包含类型,类型又包含成员,反射则提供了封装程序集、模块和类型的对象。
我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象或从现有对象中获取类型,然后调用类型的方法或访问其字段和属性。反射通常具有以下用途:
System.Reflection.Emit命名空间的类提供了一种特殊形式的反射,可以在运行时构造类型。
反射也可用于创建称为类型浏览器的应用程序,使用户能够选择类型,然后查看有关选定类型的信息。
此外,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
{
private int _num1;
private int _num2;
public Arithmetic()
{}
public Arithmetic(int num1,int num2)
{
_num1=num1;
_num2=num2;
}
public int Num1
{
get{return _num1;}
set{_num1=value;}
}
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 num2,int num2)方法是一个公有的带参数的方法";
}
private string Add()
{
return "Add()方法是一个不带参数的私有方法";
}
public static void Multiplication(int num1,int num2)
{
Console.WriteLine("{0}*{1}={2} Multiplication(int num1,int num2)是一个公有的带参数的静态方法",num1,num2,num1*num2);
}
public void Subtration(int num1,int num2)
{
Console.WriteLine("{0}-{1}={2} Subtration(int num1,int num2)是一个公有的带参数的方法",num1,num2,num1-num2);
}
private static void Multiplication()
{
Console.WriteLine("Multiplication()是一个公有的带参数的静态方法");
}
public string Write()
{
return "Write() 是一个公有的不带参数的方法";
}
public string Print()
{
return "欢迎您使用接口";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Calculator;
namespace ConsoleApplication1
{
class Program
{
delegate void TestDelegate(int num1,int num2);
static void Main(string[] args)
{
Assembly assembly=Assembly.Load("Calculator");//加载程序集
Console.WriteLine("得到Calculator.dll中的所有类");
foreach(Type var in assembly.GetTypes())
{
Console.WriteLine(var.Name+"是Calculator命明空间下的类");
}
Console.WriteLine("***************************************************");
Console.WriteLine("得到Calculator.dll中的模块集");
foreach(Module var in assembly.GetModules())
{
Console.WriteLine(var.Name+"是Calculator命明空间下的模块");
}
Console.WriteLine("***************************************************");
Console.WriteLine("");
Type type =typeof(Calculator.Arithmetic);//得到具体类的类型
Console.WriteLine("具体的类的类型是:"+type.Name);
Console.WriteLine("{0}是不是public类型:{1}",type,type.IsPublic);
Console.WriteLine("{0}是不是private类型:{1}",type ,type.IsNotPublic);
Console.WriteLine("***************************************************");
Console.WriteLine("");
foreach(PropertyInfo var in type.GetProperties())
{
Console.WriteLine(type+" 类的属性有:"+var.Name);
}
Console.WriteLine("***************************************************");
Console.WriteLine("");
foreach(Type var in type.GetInterfaces())
{
Console.WriteLine(var.Name+" 是Calculator中的接口");
}
Console.WriteLine("***************************************************");
Console.WriteLine("");
Console.WriteLine("方法的返回类型,方法的传参类型");
//查找私有方法
MethodInfo[] method_private=type.GetMethods(BindingFlags.Instance|BindingFlags.NonPublic);
foreach( MethodInfo var in method_private)
{
Console.WriteLine("私有的方法:方法名={0},方法的信息={1}",var.Name,var);
}
//查找公有方法
MethodInfo[] method_public=type.GetMethods(BindingFlags.Instance|BindingFlags.Public);
foreach( MethodInfo var in method_public)
{
Console.WriteLine("公有的方法:方法名={0},方法的信息={1}",var.Name,var);
}
//查找私有静态方法
MethodInfo[] method_pravite_static=type.GetMethods(BindingFlags.Instance|BindingFlags.NonPublic);
foreach( MethodInfo var in method_pravite_static)
{
Console.WriteLine("私有静态方法:方法名={0},方法的信息={1}",var.Name,var);
}
//查找公有静态方法
MethodInfo[] method_public_static=type.GetMethods(BindingFlags.Static|BindingFlags.Public);
foreach( MethodInfo var in method_public_static)
{
Console.WriteLine("公有静态方法:方法名={0},方法的信息={1}",var.Name,var);
}
Console.WriteLine("***************************************************");
Console.WriteLine("");
Console.WriteLine("这是构造方法的形式");
foreach(ConstructorInfo var in type.GetConstructors())
{
Console.WriteLine(var);
}
Console.WriteLine("***************************************************");
Console.WriteLine("");
object obj=Activator.CreateInstance(type,null);//创建了一个不带参数的实例
//公有非静态带参数和返回参数的方法调用
MethodInfo men1=type.GetMethod("Add");
Console.WriteLine("调用{0}方法",men1);
object[] nums1={5,4};
Console.WriteLine(men1.Invoke(obj,nums1));
Console.WriteLine("***************************************************");
Console.WriteLine("");
MethodInfo men2=type.GetMethod("Add",BindingFlags.Instance|BindingFlags.NonPublic);
Console.WriteLine(men2.Invoke(obj,null));
Console.WriteLine("***************************************************");
Console.WriteLine("");
MethodInfo men3=type.GetMethod("Multiplication",BindingFlags.Public|BindingFlags.Static);
object[] nums3={5,6};
Console.WriteLine(men3.Invoke(obj,nums3));
Console.WriteLine("***************************************************");
Console.WriteLine("");
MethodInfo men4=type.GetMethod("Multiplication",BindingFlags.NonPublic|BindingFlags.Static);
Console.WriteLine(men4.Invoke(obj,null));
Console.WriteLine("***************************************************");
Console.WriteLine("");
Console.WriteLine("动态声明的委托");
TestDelegate dele=(TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate),obj,"Subtration");
dele(9,3);
Console.WriteLine("***************************************************");
Console.WriteLine("");
}
}
}
运行结果如下图: