C#之反射

  反射是.NET的一个强大工具,通常我们很少用到反射,但是在开发一些框架或公共类库的时候使用反射会使系统架构更加灵活。了解反射能够加深我们对.NET框架的理解程度。关于反射对性能的影响,可以参考这篇文章:反射是否真的会让你的程序性能降低?

  简单来说,反射提供这样几种能力:查看和遍历类型和类型成员的元数据;动态创建类型实例,动态调用所创建的实例的方法、字段、属性;迟绑定方法和属性。

  元数据就是描述数据的数据。比如说,一个类可能是一个数据。这个类是否是公共的?这样的描述就是元数据的一种。反射通过System.Reflection命名空间的System.Type类,提供了在运行时(Runtime)对类型和类型成员的元数据的访问能力。元数据包括程序集元数据(也叫清单)和类型元数据。反射的原理就是通过读取元数据来分析模块、程序集和类型信息,可以说元数据是反射的基础。

  反射的核心是Type类,Type类封装了关于类型的元数据,也是反射的入口。当获得了类型的Type后,就可以根据Type来获取关于这个类型的方法、属性、字段、事件、参数、构造函数等一切信息。那怎么获得Type呢?

  先看看如何使用静态方法获取。

//第一种,使用静态方法调用

Type t = Type.GetType ("System.String");

Assembly a = t.Assembly;

Debug.Log ("location is :"+a.Location);

//输出为:

//location is :F:\u3d\Editor\Data\Mono\lib\mono\2.0\mscorlib.dll

   使用typeof操作符。

//第二种方法:typeof操作符

Type t2 = typeof(System.String);

MemberInfo[] mi = t2.GetMembers ();

Debug.Log ("第零个成员的名字为"+mi[0].Name);

//输出为:

//第零个成员的名字为Equals

   还可以通过类型实例来获取Type。

//第三种方法:使用实例获取type

string s = "reflection";

Type t3 = s.GetType ();

PropertyInfo[] pi = t3.GetProperties ();

for (int i = 0; i < pi.Length; i++) {

    Debug.Log(pi[i].ToString());

}

//输出为:

//System.Char Chars

//System.Int32 Length

   前面说过,Type类封装了一系列元数据,可以自己尝试输出一下。

Debug.Log ("是一个类吗:"+t.IsClass);

   通过上面获取type时的三个小示例可以初步了解type的强大功能。第一个示例通过type获取了它的程序集。程序集你可以简单的理解为程序文件的专业叫法。第二个示例通过type获取了它的成员。第三个示例通过type获取了它的属性。我们可以通过位标记来获取成员的类型信息。所谓位标记就是使用[Flags]特性标记的枚举。反射会用到很多位标记,其中之一就是MemberType位标记。

MemberInfo[] mis = t3.GetMembers ();

Debug.Log(mis[10].ToString()+", membertype is "+mis[10].MemberType);

//输出为:

//System.String[] Split(System.Char[], Int32), membertype is Method

   通过程序集反射可以轻易获得当前程序集所有type。

Assembly na = typeof(_Test).Assembly;

Module[] mo = na.GetModules ();

foreach (var item in mo) {

    Type[] ts = item.GetTypes();

    foreach (var _t in ts) {

        Debug.Log(_t.ToString());

    }

}

   _Test.class是我当前测试类的名字。它将循环输出我整个程序集的所有类型信息。当然还可以通过load方法引用其它程序集。

  MemberInfo是一个基类,它所包含的是所有类型成员所共有的一组信息。不仅FieldInfo、PropertyInfo、MethodInfo、ParameterInfo、EventInfo、ConstructorInfo等继承自它,连Type类也继承自它。因为一个type也可能是另一个type的成员。这些info的用法没有必要记住,用的时候查一下就可以了。

  至于通过反射创建类型实例这个我认为很少用到。那什么是迟绑定呢?所谓的方法迟绑定也就是基于字符串的方法调用。我这个方法是以字符串的形式调用的,那么只有当实际调用的时候才知道究竟是哪个方法,其它时候它不过是一个字符串而已。基于字符串的方法调用很简单,应用也稍微多一点点。

//声明一个类

class dog{

    public void Speak(){Debug.Log ("speaking .....");}

}



//基于字符串的方法调用

Type t4 = typeof(dog);

dog d = new dog();



//通过type调用

t4.InvokeMember("Speak",BindingFlags.InvokeMethod,null,d,null);

        

//通过MethodInfo调用

MethodInfo mm = t4.GetMethod ("Speak");

mm.Invoke (d, null);

 

你可能感兴趣的:(C#)