• 反射


    一、定义

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

    二、用法

    首先创建一个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:BaseWork1TestDLLinDebug1TestDLL.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:BaseWork2TestDLLinDebug2TestDLL.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语言,发现静态类,接口其实就是抽象类。

  • 相关阅读:
    scanf与scanf_s的区别
    C语言输出时的各种%
    Windows下配置OpenGL环境
    C#高级进阶--重写函数
    Linux下安装国际版QQ (转)
    Linux Vim不明原因卡死解决办法
    iCamera App Kit 使用说明
    usb2.0高速视频采集之68013A寄存器配置说明
    iSensor APP 之 摄像头调试 OV5642 续集2
    iSensor APP 之 摄像头调试 OV9655 测试之二
  • 原文地址:https://www.cnblogs.com/wesley168/p/6807238.html
Copyright © 2020-2023  润新知