日期:2014-05-17  浏览次数:20887 次

C#反射(Reflection),特性(Atrribute)

反射定义

   反射就是审查元数据并收集关于它的类型信息的能力.

    那元数据又是个啥东东呢?元数据是程序集里的东西. 我们知道程序编译之后会生成很多dll,它就是程序集,一般是一个project对应一个程序集吧.一个程序集(assembly)就是一个dll或exe文件(不过据说有多文件程序集,不知道是不是一个程序集是多个dll,没研究过啊).当然不是所有的dll文件都叫程序集.其他程序语言,比如C++中也会有dll,我们一般就叫动态链接库.不是程序集.程序集里除了可执行指令外还有元数据.元数据就是一大堆的表,有类定义表,字段定义表,方法定义表.另外还有版本等信息.它有点像个目录一样,告诉我们程序集中有些啥内容.

   我们大部分时候应该是不需要去知道程序集里元数据的信息的.也就是不需要用到反射的.那啥时候需要用反射呢?

   正常情况下我们要使用某个dll的话直接添加引用,然后引用命名空间.接下来就可以使用其中的类了.那如果事先约定好某个dll中会有些啥类和函数.但是那dll还没做好.你写代码时又要用到,那咋整啊.总不能傻等着别人做完你再写代码吧.另外如果那dll暂时没打算写,等以后再扩充就更是如此了.这会就可以用到反射了.你可以先写代码Load某个dll(不一定要实际存在),然后获取里面类和函数信息,然后调用.这是调用别的dll时用到,调用本身所在的dll也可以用到反射,比如一般软件都会有个"关于"的菜单选项,点下会弹出软件的版本信息.通过从程序集中可以获取版本信息,不用再去注册表或其他哪去获取了.另外我们用VS时智能感应让我们用起来很方便,随便敲几个字母带出一堆信息.这里也是用到反射.

特性(atrribute)定义

   atrribute有时也被翻译成属性,但是容易和property(属性)混淆.atrribute指可以应用到代码块(比如类,方法,属性)上的额外信息.

   比如我们在使用序列化的时候会用到特性[Serializable],当要想把某个类序列化必须得在类前面加个这样的特性.特性的用法就是一个中括号号,然后里面加些啥信息.

  除了使用类库定义好的特性我们还可以自定义些特性.特性的信息会被保存到程序集中,反射的时候可以用到.

反射具体用法

举个简单例子,假如有个dll文件MyDll.dll,里面有个类YourName,类里有个方法ShowYourName().现在想通过动态加载这个dll然后通过反射去实例化类YourName,并调用类中的方法.

dll中类YourName的定义如下

using System;

namespace MyDll

{

    class YourName

    {

        public void ShowYourName()

        {

            Console.WriteLine("Hi,I am arwen.");

        }

    }

}

调用的代码如下.先引用命名空间using System.Reflection;

string dllPath = @"D:\MyDll.dll";   //dll文件所在路径

Assembly asm = Assembly.LoadFrom(dllPath);  //动态加载dll

Type yourName = asm.GetType("MyDll.YourName");     /*获取类型YourName.Type可以代表反射获得的class,interface等任何类型.有点像object可以代表任何类一样了*/

object obj = Activator.CreateInstance(yourName);         //实例化类YourName

MethodInfo function = yourName.GetMethod("ShowYourName");     //获取方法ShowYourName

function.Invoke(obj, null);      //调用方法ShowYourName

自定义特性用法

举个简单的例子,新建一个用来添加注释的特性,其实自定义特性就是新建一个class

class MyAtrribute: Attribute                  //必须继承Atrribute,其它就跟一般类完全一样

    {

        public string Note { get; set; }

        public MyAtrribute(string msg)

        {

            Note = msg;

        }

        public void ShowNote()

        {

           Console.WriteLine(Note);

          }

    }

然后在类前面添加

[MyAtrribute("this class is used for showing your name")]

class YourName

{

      //就用前面的类YourName

}

 

在反射中使用自定义特性的信息

string dllPath = @"D:\MyDll.dll";  

Assembly asm = Assembly.L