反射

一、定义

反射是一种 通过动态读取程序集,获取其中的类型元数据,并且对其进行访问的 技术。

二、用法

首先创建一个Person类。

 1 public class Person
 2     {
 3         private int _size;
 4         public string Name { get; set; }
 5         public int Age { get; set; }
 6         public int Gender { get; set; }
 7         public void Say()
 8         {
 9             Console.WriteLine("hello !");
10         }
11 
12         public void SayHello()
13         {
14             Console.WriteLine("hello ,everyone !");
15         }
16 
17         void Introduce()
18         {
19             Console.WriteLine("i am wesley");
20         }
21     }
View Code

1.Type对象

接下来使用反射中的重要对象Type访问Person中的类型元数据。使用Type对象,有两种方式。

第一种方式:Type personType = typeof(Person);

1 Type personType = typeof(Person);
2             MemberInfo[] members = personType.GetMembers();
3             for (int i = 0; i < members.Length; i++)
4             {
5                 Console.WriteLine(members[i].Name);
6             }
View Code

输出结果:

 1 //get_Name
 2             //set_Name
 3             //get_Age
 4             //set_Age
 5             //get_Gender
 6             //set_Gender
 7             //Say
 8             //SayHello
 9             //ToString
10             //Equals
11             //GetHashCode
12             //GetType
13             //.ctor
14             //Name
15             //Age
16             //Gender
View Code

包括编译器自动生成的与属性对应的方法,继承自object的方法,但是不包括私有方法。如果需要访问私有方法,需要用其他方式。

第二种方式: Person person = new Person();  Type personType= person.GetType();

 1  Person person = new Person();
 2             Type personType= person.GetType();
 3 
 4             //获取所有方法,私有的方法不能获取
 5             MethodInfo[] methods = personType.GetMethods();
 6             for (int i = 0; i < methods.Length; i++)
 7             {
 8                 Console.WriteLine(methods[i].Name);
 9             }
10 
11             //所有属性
12             PropertyInfo[] properties=  personType.GetProperties();
13             for (int i = 0; i < properties.Length; i++)
14             {
15                 Console.WriteLine(properties[i].Name);
16             }
View Code

用Type对象还能访问其他类型元数据,具体可以查看文档或者对象中的成员。

2.Assembly

先创建一个类库,里面有类,接口,委托等,代码如下:

 1 namespace _01TestDLL
 2 {
 3     class Test
 4     {
 5     }
 6 
 7     public class Person
 8     {
 9         private int _size;
10         public string Name { get; set; }
11         public int Age { get; set; }
12         public int Gender { get; set; }
13         public void Say()
14         {
15             Console.WriteLine("hello !");
16         }
17 
18         public void SayHello()
19         {
20             Console.WriteLine("hello ,everyone !");
21         }
22 
23         void Introduce()
24         {
25             Console.WriteLine("i am wesley");
26         }
27 
28         public int Add(int n1,int n2)
29         {
30             return n1 + n2;
31         }
32 
33         //public int Add(int n1, int n2,int n3)
34         //{
35         //    return n1 + n2 + n3;
36         //}
37     }
38 
39     class MyClass
40     { }
41 
42     public delegate void M1Delegate();
43 
44     delegate void M2Delegate();
45 
46     interface IDriveAble { }
47 
48     public interface IFlyAble
49     {
50         void Fly();
51     }
52 
53     public class Student
54     {
55 
56     }
57 
58     public class Teacher : IFlyAble
59     {
60         public void Fly()
61         {
62             Console.WriteLine("i can fly ,see me fly high !");
63         }
64     }
65 }
View Code

把上面的类库生成dll,用Assembly读取。

显示dll中的所有类型元数据:

 1   Assembly assembly = Assembly.LoadFile(@"F:\BaseWork\01TestDLL\bin\Debug\01TestDLL.dll");
 2 
 3             //Console.WriteLine(assembly.GetType().Name);
 4 
 5             //这种方式输出程序集中的所有类型元数据
 6             Type[] types1 = assembly.GetTypes();
 7             foreach (var item in types1)
 8             {
 9                 Console.WriteLine(item.Name);
10             }
11 
12             //只显示public的类型元数据
13             Type[] types = assembly.GetExportedTypes();
14             foreach (var item in types)
15             {
16                 Console.WriteLine(item.Name);
17             }
View Code

 访问Person类中无参无返回值的Say方法:

 1 #region 调用程序集中无参无返回值的方法
 2             Type personType = assembly.GetType("_01TestDLL.Person");
 3 
 4             MethodInfo method = personType.GetMethod("Say");
 5 
 6             object obj = Activator.CreateInstance(personType);
 7 
 8             //我们不能直接创建要调用的方法所在的类的对象(如果可以创建对象,我们直接可以调用该类中的方法了,没必要再用反射),所以用上一行代码创建对象
 9             method.Invoke(obj, null);//第一个参数:当前要调用的方法所在的类的对象;第二个参数:要调用的方法的参数列表
10             #endregion
View Code

调用Person类中有参数有返回值的方法(Add(int n1,int n2)):

1 #region 调用程序集中有参数有返回值的方法
2             Type personType = assembly.GetType("_01TestDLL.Person");
3 
4             MethodInfo method = personType.GetMethod("Add");
5             object obj = Activator.CreateInstance(personType);
6             int res = (int)method.Invoke(obj, new object[] { 1, 2 });
7             Console.WriteLine(res);
8             #endregion
View Code

调用Person类中Add的重载方法(Add(int n1,int n2,int n3)):

1 #region 调用程序集中重载的方法
2             //如果Add方法有重载,则需要区分方法是否重载
3             Type personType = assembly.GetType("_01TestDLL.Person");
4             MethodInfo method = personType.GetMethod("Add", new Type[] { typeof(int), typeof(int), typeof(int) });
5             object obj = Activator.CreateInstance(personType);
6             int res = (int)method.Invoke(obj, new object[] { 1, 2, 3 });
7             Console.WriteLine(res);
8             #endregion
View Code

 给属性赋值,取值

 1 #region 给属性赋值,并且取值
 2             Type personType= assembly.GetType("_01TestDLL.Person");
 3             PropertyInfo proper= personType.GetProperty("Name");
 4             //object obj= assembly.CreateInstance("_01TestDLL.Person");//和下面的代码效果一样
 5             object obj = Activator.CreateInstance(personType);
 6             proper.SetValue(obj, "张三");
 7 
 8             string name= proper.GetValue(obj, null).ToString(); ;
 9             Console.WriteLine(name);
10             #endregion
View Code

先在Person类中添加一个方法和构造函数,然后调用构造函数,创建对象

方法和构造函数

 1 public Person(string name,int age)
 2         {
 3             this.Name = name;
 4             this.Age = age;
 5         } 
 6 
 7 public void GetPropertiesValue()
 8         {
 9             Console.WriteLine(this.Name+"   "+this.Age);
10         }
View Code
调用构造函数,创建对象
 1  #region 调用构造函数,创建对象
 2             Type typePerson = assembly.GetType("_01TestDLL.Person");
 3             ConstructorInfo ctor = typePerson.GetConstructor(new Type[] { typeof(string), typeof(int) });
 4 
 5             object obj= ctor.Invoke(new object[] { "张三", 18 });
 6 
 7             MethodInfo method= typePerson.GetMethod("GetPropertiesValue");
 8             method.Invoke(obj, null);
 9 
10             #endregion
View Code

3.Type的其他常用方法和属性

先创建类和获取程序集:

 1 namespace _02TestDLL
 2 {
 3     public class Person
 4     {
 5         public void Introduce()
 6         {
 7             Console.WriteLine("我是人类");
 8         }
 9     }
10 
11     public interface IFlyAble
12     {
13         void Fly();
14     }
15 
16     public abstract class MyAbstractClass
17     {
18 
19     }
20 
21     public static class MyStaticClass
22     {
23 
24     }
25 
26     public class Student : Person, IFlyAble
27     {
28         public void Fly()
29         {
30             throw new NotImplementedException();
31         }
32     }
33 }
View Code

程序集:

1 Assembly assembly = Assembly.LoadFile(@"F:\BaseWork\02TestDLL\bin\Debug\02TestDLL.dll");
View Code

 IsAssignableFrom():判断当前实例是不是可以接收传入的实例

 1 Type typePerson = assembly.GetType("_02TestDLL.Person");
 2 
 3             Type typeStudent = assembly.GetType("_02TestDLL.Student");
 4 
 5             Type typeIFlyAble = assembly.GetType("_02TestDLL.IFlyAble");
 6 
 7             bool bPerson = typePerson.IsAssignableFrom(typeStudent);
 8 
 9             Console.WriteLine(bPerson);
10 
11             //输出true
View Code

IsInstanceOfType():判断指定的实例是不是当前类型的实例

1  Type typePerson = assembly.GetType("_02TestDLL.Person");
2             Type typeStudent = assembly.GetType("_02TestDLL.Student");
3             Object obj = Activator.CreateInstance(typeStudent);
4 
5             bool b = typePerson.IsInstanceOfType(obj);
6             Console.WriteLine(b);
7             //输出true
View Code

IsSubclassOf():判断当前Type表示的类是不是从指定的类派生的

1  Type typePerson = assembly.GetType("_02TestDLL.Person");
2             Type typeStudent = assembly.GetType("_02TestDLL.Student");
3             bool b = typeStudent.IsSubclassOf(typePerson);
4             Console.WriteLine(b);
5             //输出true
View Code

IsAbstract:判断当前Type表示的类是不是抽象的,包括接口和静态类

 1 Type typeMyStaticClass = assembly.GetType("_02TestDLL.MyStaticClass");
 2             Type typeMyAbstractClass = assembly.GetType("_02TestDLL.MyAbstractClass");
 3             Type typeIFlyAble = assembly.GetType("_02TestDLL.IFlyAble");
 4 
 5             bool b1 = typeMyStaticClass.IsAbstract;
 6             Console.WriteLine(b1);
 7 
 8             bool b2 = typeMyAbstractClass.IsAbstract;
 9             Console.WriteLine(b2);
10 
11             bool b3 = typeIFlyAble.IsAbstract;
12             Console.WriteLine(b3);
13             //输出true
View Code

 用IsAbstract属性判断时,发现静态类,接口也返回true,反编译后查看IL语言,发现静态类,接口其实就是抽象类。

posted @ 2017-05-04 15:09  wesley1680  阅读(138)  评论(0编辑  收藏  举报