Fork me on GitHub
听雨轩
生命易破碎,梦想只争朝夕!

     反射是一种机制,通过这种机制我们可以知道一个未知类型的类型信息.比如,有一个对象a,这个对象不是我们定义的,也许是通过网络捕捉到的,也许是使用泛型定义的,但我们想知道这个对象的类型信息,想知道这个对象有哪些方法或者属性什么的.甚至我们想进一步调用这个对象的方法.关键是现在我们只知道它是一个对象,不知道它的类型,自然不会知道它有哪些方法等信息.这时我们该怎么办?反射机制就是解决这么一个问题的.通过反射机制我们可以知道未知类型对象的类型信息.
  再比如,我们有一个dll文件,我们想调用里面的类.现在假设这个dll文件的类的定义,数量等不是固定的,是经常变化的.也许某一天你要在这个dll里面增加一个类定义.也许你觉得这没什么问题,现在关键是我们在另一个程序集里面要调用这个dll,这是我们的程序必须能够适应这个dll的变化,也就是说即使改变了dll文件的定义也不需要改变我们的程序集.这时候我们就会使用一个未知dll.我们该怎么办?同样,反射机制帮助了我们,我们可以通过反射来实现.

下面我举一个例子说明:

首先我新建一个控制台应用程序,然后添加一个类库Model,在类库中添加一个类People.cs如下:

namespace Model
{
    public class People
    {
        public string name { get; set; }
        public string sex { get; set; }
        public int age { get; set; }

        public string GetName()
        {

            return "我的名字是" + name;
        }

        public string Display()
        {
            return "我的名字是:" + name + "\n我的性别是:" + sex + "\n我的年龄:" + age+"\n";
        
        }
        public People(string name,string sex,int age)
        {
            this.name = name;
            this.sex = sex;
            this.age = age;
        
        
        }


    }
}

然后在main函数中些如下代码:

static void Main(string[] args)
        {
            var asssembly = Assembly.Load("Model");//加载程序集
            Console.WriteLine("程序集名称:{0}", asssembly.FullName);
               Console.WriteLine();

            Type people = asssembly.GetType("Model.People");//获取类型信息,这里要写完整的名称
            Object[] PeopleParms = new object[] {"袁安云","男",22}; //构造器参数,这就要求重载构造函数,如果我想这样写me.name="袁安云",多方便啊,
//不过这样的话,需要强制类型转换,如:var you=(Model.People)me,然后you.name="袁安云";
            Object me = Activator.CreateInstance(people,PeopleParms);//根据类型创建对象
            MethodInfo method = people.GetMethod("Display");//获取方法的信息
            Console.WriteLine(method.Invoke(me, null));//调用方法,第二个参数为方法的参数,是一个object类型数组,不需要参数时设为null

                    Console.ReadKey();
            

        }

运行结果:

说明:

在VS.Net中,有很多种方法动态调用对象的构造函数。一是通过Activator类的CreateInstance()方法。这个方法我们在Remoting中也用过。它实际上是在本地或从远程创建对象类型,或获取对现有远程对象的引用。它的方法签名是:public static object CreateInstance(Type);(还有其他重载方法)注意它的返回值为object,MSDN对返回值的描述是:对新创建对象的引用。
二是通过Assembly类的方法CreateInstance()。方法名和前一样,不过它不是静态方法。Assembly是在System.Reflection命名空间中。方法签名:public object CreateInstance(Type);(同样还有其他重载方法)返回值仍然是object,MSDN对返回值的描述是:表示该类型的 Object 的实例,其区域性、参数、联编程序和激活属性设置为空引用(Visual Basic 中为 Nothing),并且 BindingFlags 设置为 Public 或 Instance,或者设置为空引用 (Nothing)(如果没有找到 typeName)。

当然还有其他方法,例如通过MethodInfo获得方法信息后,根据IsConstructor属性,判断是否构造函数,再根据GetParamters()方法获得参数,最后通过Invoke()方法来调用,等等……。大家可以参考MSDN。

问题:

以上调用方法Display是这样实现的:

            MethodInfo method = people.GetMethod("Display");//获取方法的信息
            Console.WriteLine(method.Invoke(me, null));//调用方法,第二个参数为方法的参数,是一个object类型数组,不需要参数时设为null

如果我想这样写me.Display(),该如果实现呢?采用强制类型转换即可:

  var you = (Model.People) me;
  Console.WriteLine(you.Display());

 

 


 

posted on 2010-10-25 15:24  流水殇  阅读(406)  评论(0编辑  收藏  举报