反射

反射式动态获取程序集的元数据的功能

VS的只能提示和反编译就是使用的反射。

反射的一个重要的类是Type,其可获得一个类型的类型,通过这个我们可以获取类中的所有信息,包括方法、属性。 可以动态调用类的属性、方法。

反射是通过.dll来创建对象,调用成员。

对于已经已经生成的类库,在另一个项目中引用时,可以通过反射获取该类库中的元数据。

1. 已写好的类库:Common.dll

Person.cs

using System;
using System.IO;

namespace Common
{
    public class Person
    {
        public void Write()
        {
            Console.WriteLine("good cat");
        }

        public int Age { get; set; }

        public string Name { get; set; }

        public void SayHi()
        {
            Console.WriteLine("Person Method");
        }

        public Person(string name)
        {
            Name = name;
        }

        public Person()
        {

        }
    }

    class Cat
    {
        public string Eat { get; set; }
        string catName;
    }
}

2. 将Common.dll文件拷贝到引用项目的可执行文件所在目录

3. 引用项目:

Program.cs

using System;
using System.Collections.Generic;
using System.IO; //Assembly
using System.Reflection;

namespace 反射
{
    class Program
    {
        static void Main(string[] args)
        {
            //添加引用有些麻烦,而且只能使用其中的公共成员
            //对于给定的dll文件,想要使用里面的所有成员

            //首先加载程序集文件
            //获取当前程序的exe所在目录+文件名=文件所在的绝对目录
            string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Common.dll");
            Assembly asse = Assembly.LoadFile(path);
            Console.WriteLine("加载程序集成功。");
            #region 获取程序集类型的3个函数

            //获取程序集中的类型:公共和私有
            Console.WriteLine("1. GetTypes()");
            Type[] allTypes = asse.GetTypes();
            foreach(Type item in allTypes)
            {
                Console.WriteLine(item.Name);
                Console.WriteLine(item.FullName);
                Console.WriteLine(item.Namespace);
            }

            Console.WriteLine();
            //获取程序集中定义的公共类型,这些类型在程序集外可见
            Console.WriteLine("2. GetExportedTypes()");
            Type[] publicTypes = asse.GetExportedTypes();
            foreach(Type item in publicTypes)
            {
                Console.WriteLine(item.Name);
                Console.WriteLine(item.FullName);
                Console.WriteLine(item.Namespace);
            }

            Console.WriteLine();
            //获取单个类型
            Console.WriteLine("3. GetTypes(\"Common.Person\").Name");
            Type t = asse.GetType("Common.Person");
            Console.WriteLine(t.Name);
            #endregion

            Console.WriteLine();
            //从获取的类型来创建对象
            //CreateInstance从程序集中查找指定的类型,然后使用系统激活器
            //创建它的实例,调用了Person的默认无参数的构造函数,而不能调用
            //有参的构造函数
            Console.WriteLine("4. CreateInstance(\"Common.Person\").GetType()");
            object o = asse.CreateInstance("Common.Person");
            Console.WriteLine(o.GetType());

            Console.WriteLine();
            //可以指定要用的构造函数
            Console.WriteLine("5. 指定要用的构造函数Activator来CreateInstance");
            Type tt = asse.GetType("Common.Person");
            object o1 = Activator.CreateInstance(tt,"PersonName");
            PropertyInfo[] proInfos = o1.GetType().GetProperties();
            foreach(PropertyInfo item in proInfos)
            {
                Console.WriteLine(item.Name);
            }

            Console.WriteLine();
            MethodInfo[] mths = o1.GetType().GetMethods();
            foreach (MethodInfo item in mths)
            {
                Console.WriteLine(item);
            }

            Console.WriteLine("获取指定函数的信息");
            MethodInfo mdi = o1.GetType().GetMethod("SayHi");
            //方法所属对象,函数参数列表
            mdi.Invoke(o1,null);
            
            //IsAssignableFrom(Type c)判断当前的类型是否可以接收C类型变量的赋值
            //typeof(IPlugin).IsAssignableFrom(t)
            //isInstanceOfType(object o):判断对象O是否为当前类的实例
            //bool IsSubclassOf(Type c):判断当前类是否为c的子类
            //IsAbstract判断是否为抽象,含接口

            Console.ReadKey();
        }
    }
} 

4. 输出

 

posted @ 2017-12-01 18:29  mCat  Views(185)  Comments(0Edit  收藏  举报