• .Net中的反射


    反射

    使用反射,可以在程序运行时创建、调用和访问类型实例。 

    程序集(Assembly)包含模块(Module)、模块包含类型(Type),而类型包含成员(Member)。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。

    简单的来说,就是平常我们创建类实例,访问类成员函数、变量等,都是在开发环境中写好代码再去执行。使用反射后,可以在程序运行时,执行上述操作。

    反射有时候也会用,这算是一个比较系统的总结了吧。

    反射的典型用法

    • 使用 Assembly 来定义和加载程序集,加载程序集清单中列出的模块,以及在此程序集中定位一个类型并创建一个它的实例。

    • 使用 Module 发现信息,如包含模块的程序集和模块中的类。 还可以获取所有全局方法或模块上定义的其它特定的非全局方法。

    • 使用 ConstructorInfo 发现信息,如名称、参数、访问修饰符(如 public 或 private)和构造函数的实现详细信息(如 abstract或 virtual)。 使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定构造函数。

    • 使用 MethodInfo 发现信息,如名称、返回类型、参数、访问修饰符(如 public 或 private)和方法的实现详细信息(如 abstract 或 virtual)。 使用 Type 的 GetMethods 或 GetMethod 方法来调用特定方法。

    • 使用 FieldInfo 发现信息,如名称、访问修饰符(如 public 或 private)和一个字段的实现详细信息 (如 static);并获取或设置字段值。

    • 使用 EventInfo 发现信息(如名称、事件处理程序的数据类型、自定义特性、声明类型以及事件的反射的类型),并添加或删除事件处理程序。

    • 使用 PropertyInfo 发现信息(如名称、数据类型、声明类型,反射的类型和属性的只读或可写状态),并获取或设置属性值。

    • 使用 ParameterInfo 发现信息,如参数的名称、数据类型、参数是输入参数还是输出参数以及参数在方法签名中的位置。

    • 使用 CustomAttributeData 在于应用程序域的仅反射上下文中工作时发现有关自定义特性的信息。 CustomAttributeData 使你能够检查特性,而无需创建它们的实例。

    System.Type

    表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型

    Type是一个抽象的基类,实例化了一个Type对象,实际上就实例化了Type的一个派生类。

    获取给定类型的Type引用有3种常用方式:

    1、使用typeof运算符

    1 var strType = typeof(string);

    2、使用GetType()方法,所有的类都会从System.Object继承这个方法

    1      string str = "HelloWorld";
    2      var strType2 = str.GetType();

    3、使用Type类的静态方法GetType

    1 var t = Type.GetType("System.String");

    System.Type常用属性

    属性 返回值
    Name 数据类型名
    FullName 数据类型的完全限定名(包括命名空间)
    Namespace 数据类型的命名空间
    BaseType

    该Type的直接基本类型

    Module 该类型的模块 (DLL)
    Assembly   该类型的 Assembly
     1 class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             var t = Type.GetType("System.String");
     6             Console.WriteLine(t);
     7 
     8 
     9             Console.WriteLine("Name:" + t.Name);
    10             Console.WriteLine("FullName:" + t.FullName);
    11             Console.WriteLine("Namespce:" + t.Namespace);
    12             Console.WriteLine("BaseType:" + t.BaseType);
    13             Console.WriteLine("Assembly:" + t.Assembly.FullName);
    14             Console.WriteLine("Module:" + t.Module.Name);
    15         }
    16     } 

    Type类包含许多Is开头的属性,这些属性用于判断该Type是否属于该类型。常用的如下:

    属性 说明
    IsAbstract

    是否是抽象类型

    IsArray

    是否为数组

    IsByRef

    是否是引用传递

    IsClass

    是否是一个类或委托

    IsCOMObject

    是否为 COM 对象

    IsConstructedGenericType

    是否表示构造的泛型类型的值

    IsContextful

    指示 Type 在上下文中是否可以被承载

    IsEnum

    是否是枚举

    IsExplicitLayout

    是否放置在显式指定的偏移量处的值

    IsGenericMethodParameter

    是否表示泛型方法定义中的类型参数

    IsGenericParameter

    是否表示泛型类型或方法的定义中的类型参数

    IsGenericType

    是否是泛型类型

    IsGenericTypeDefinition

    是否表示可以用来构造其他泛型类型的泛型类型定义

    IsGenericTypeParameter

    是否表示泛型类型定义中的类型参数

    IsImport

    是否应用了 ComImportAttribute 属性

    IsInterface

    是否是接口

    IsLayoutSequential

    是否按顺序(定义顺序或发送到元数据的顺序)放置的值

    IsMarshalByRef

    是否按引用进行封送

    IsNested

    是否表示其定义嵌套在另一个类型的定义之内的类型的值

    IsNestedAssembly

    是否是嵌套的并且只能在它自己的程序集内可见

    IsPointer

    是否是指针

    IsPrimitive

    是否为基元类型之一

    IsPublic

    是否声明为公共类型

    IsSealed

    是否声明为密封的

    IsSerializable

    是否为可序列化的

    IsValueType

    是否为值类型

    IsVisible

    是否可由程序集之外的代码访问的值

    System.Type常用方法

    System.Type的大多数方法都用于获取对应数据类型的成员信息:构造函数、属性、方法和事件等。

    方法 说明
    GetConstructors 获取所有公共构造函数
    GetEvents 获取所有公共事件所有公共事件
    GetFields 获取所有公共字段
    GetMembers 获取所有公共成员
    GetMethods 获取所有公共方法
    GetProperties 获取所有公共属性

    这里我们用WPF的Button类来进行演示:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace ReflectionDemo
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             var buttonType = typeof(System.Windows.Controls.Button);
    14 
    15             var ctors = buttonType.GetConstructors();
    16             var events = buttonType.GetEvents();
    17             var fields = buttonType.GetFields();
    18             var members = buttonType.GetMembers();
    19             var methods = buttonType.GetMethods();
    20             var properties = buttonType.GetProperties();
    21 
    22             Console.WriteLine(buttonType.Assembly.FullName);
    23             PrintResult(ctors, "Constructors");
    24             PrintResult(events, "Events");
    25             PrintResult(fields, "Fields");
    26             PrintResult(members, "Members");
    27             PrintResult(methods, "Methods");
    28             PrintResult(properties, "Properties");
    29         }
    30 
    31         static void PrintResult(object[] array, string title = "")
    32         {
    33             Console.WriteLine(title);
    34             foreach (var item in array)
    35             {
    36                 Console.WriteLine(item);
    37             }
    38             Console.WriteLine();
    39             Console.WriteLine();
    40         }
    41     }
    42 }

    此外,System.Type还提供了单数形式的方法,如t.GetMethod()、t.GetEvent()。单数形式的方式用于返回指定名称的值。

    如:

    1 var buttonType = typeof(System.Windows.Controls.Button);
    2 var clickEvent = buttonType.GetEvent("Click");

    在前面的示例代码中,我们输出 了string类型的Assembly,如下:

    1 Assembly:mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

    mscorlib.dll是我们引用的程序集,如果需要加载外部 程序集并获取类型信息,就需要使用Assembly类

    System.Reflection.Assembly

    Assembly类允许访问给定程序集的元数据,同时它也包含可以加载程序集的方法。

    要将程序集加载到正在运行的程序中,可以通过两个方法:Assembly.Load()Assembly.LoadFrom()

    这两个方法的区别是:

    Assembly.Load()的参数是指定程序集名称,运行库会在各个位置(运行目录和GAC)搜索该程序集,试图找到该程序集。

    Assembly.LoadFrom()的参数是指定程序集的完整路径,它不会在其它位置搜索该程序集

    推荐阅读:

    反射

    https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/reflection

  • 相关阅读:
    线程同步之条件变量使用手记
    如何实现文件增量同步——算法
    javascript 复习笔记
    cocos2dx 多图层点击事件及管理相关问题记录
    cocos2dx 2.1.1 jsbinding 游戏帧数下降问题记录
    cocos2dx jsb + cocosbuilder 编译到安卓下问题处理(待续)
    cocos2dxjsb及Cocosbuilder使用相关问题处理记录
    cocos2dx jsb 的本地存储
    cocos2dxjsb 跨语言调用及第三方集成 过程记录
    cocos2dx 2.1.1 升级2.1.3版本 记录
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/14122049.html
Copyright © 2020-2023  润新知