上一篇文章中,介绍如何获取 Type 类型,Type 类型是反射的基础。

本篇文章中,将使用 Type 去获取成员信息,通过打印出反射获取到的信息,为后续操作反射打好基础。

1,获取类型的信息

我们常常可以看到 函数、方法这两个词,很多人对此进行了混用。

方法,就是 public void Test(){} 这样的形式;

函数,指具有确定命名的、并且可以通过名称调用的代码,属性、字段、方法、委托、事件等;

只要能够通过确定的名称调用(使用)的代码块,就是函数;而方法就是 返回值、名称、参数等组成的代码块;

要操作反射,首先要获取到 类型 的反射信息,而类型的 Type ,与以下多种类型密切相关。

类型 说明
Assembly 加载程序集、读取程序集信息、获取类型等
Module 访问程序集中的一个或多个模块
PropertyInfo 类型的属性信息
FieldInfo 类型的字段信息
ConstructorInfo 类型的构造函数信息
MethodInfo 类型的方法
ParameterInfo 构造函数或方法的参数
EventInfo 类型的事件
MemberInfo 成员信息,集成以上除 Assembly、Module 外所有的类型

1.1 类型的基类和接口

1.1.1 基类

C# 中,一个类型只能继承一个类型(基类型),使用实例Type.BaseType 属性,可以获取到此类型的基类型。

            Type type = typeof(MyClass);
Type baseType = type.BaseType;

1.1.2 获取实现的接口

GetInterface()GetInterfaces() 可以获取类型实现的接口。

示例

            Type type = typeof(System.IO.FileStream);
Type[] list = type.GetInterfaces();
foreach (var item in list)
Console.WriteLine(item.Name);

输出

IDisposable
IAsyncDisposable

1.1.3 获取泛型接口

            Type type = typeof(List<>);
Type one = type.GetInterface("IList`1");
Console.WriteLine(one.Name);
Console.WriteLine("***************");
Type[] list = type.GetInterfaces();
foreach (var item in list)
Console.WriteLine(item.Name);

输出

IList`1
***************
IList`1
ICollection`1
IEnumerable`1
IEnumerable
IList
ICollection
IReadOnlyList`1
IReadOnlyCollection`1

注意的是,如果要通过名称获取接口 Type ,需要使用 泛型类别的名称,例如 IList1`。

1.2 获取属性、字段成员

1.2.1 构造函数

一个类型最少不了的就是构造函数,即使没有编写构造函数,C# 编译时也会生成默认的构造函数。

GetConstructor()GetConstructors() 可以获取构造函数 ConstructorInfo 类型;

ConstructorInfoGetParameter()GetParameters() 可以获取构造函数的参数信息;

创建一个类

    public class MyClass
{
static MyClass() { }
public MyClass() { }
private MyClass(string a) { }
public MyClass(int a) { }
}

打印

            Type type = typeof(MyClass);
ConstructorInfo[] list = type.GetConstructors();
foreach (var item in list)
{
Console.WriteLine(item.Name + " | " + item.IsStatic + " | " + item.IsPublic);
ParameterInfo[] parms = item.GetParameters();
foreach (var itemNode in parms)
{
Console.WriteLine(itemNode.Name + " | " + itemNode.ParameterType + " | " + itemNode.DefaultValue);
}
}

输出

.ctor   |   False   |   True
.ctor | False | True
a | System.Int32 |

上面结果说明了,只能获取 Public 的构造函数;

关于 ConstructorInfo 的使用方法,可以参考这里 https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.constructorinfo?view=netcore-3.1

1.2.2 属性

使用 GetPropertie()GetProperties() 可以获取 类型 的一个或多个属性。

            Type type = typeof(Type);
PropertyInfo[] list = type.GetProperties();
foreach (var item in list)
Console.WriteLine(item.Name + " | " + item.PropertyType);

输出

IsInterface  |  System.Boolean
MemberType | System.Reflection.MemberTypes
Namespace | System.String
AssemblyQualifiedName | System.String
FullName | System.String
Assembly | System.Reflection.Assembly
Module | System.Reflection.M

1.2.3 字段

使用 GetField()GetFields() 可以获取类型的一个或多个字段。

            Type type = typeof(Type);
FieldInfo[] list = type.GetFields();
foreach (var item in list)
Console.WriteLine(item.Name + " | " + item.FieldType + " | " + item.IsPublic);

输出

Delimiter  |  System.Char    |   True
EmptyTypes | System.Type[] | True
Missing | System.Object | True
FilterAttribute | System.Reflection.MemberFilter | True
FilterName | System.Reflection.MemberFilter | True
FilterNameIgnoreCase | System.Reflection.MemberFilter | True

这里有个问题,获取到的所有字段,都是 Public 的?

到底是 Type 里面的字段都是 Public 的,还是反射只能获取到类型 Public 字段?

我们通过实验验证一下。

创建一个类

    public class MyClass
{
public string A { get; set; } // 不公开的属性,一般不会这样写
private string B { get; set; } public string C;
protected string D;
internal string E;
private string G;
}

打印

            Type type = typeof(MyClass);

            PropertyInfo[] listA = type.GetProperties();
// 属性没有 item.IsPublic 等
foreach (var item in listA)
Console.WriteLine(item.Name + " | " + item.PropertyType); Console.WriteLine("**************"); IEnumerable<PropertyInfo> listB = type.GetRuntimeProperties();
foreach (var item in listB)
Console.WriteLine(item.Name + " | " + item.PropertyType); Console.WriteLine("**************"); FieldInfo[] listC = type.GetFields();
foreach (var item in listC)
Console.WriteLine(item.Name + " | " + item.FieldType + " | " + item.IsPrivate + " | " + item.IsPublic); Console.WriteLine("**************"); IEnumerable<FieldInfo> listD = type.GetRuntimeFields();
foreach (var item in listD)
Console.WriteLine(item.Name + " | " + item.FieldType + " | " + item.IsPrivate + " | " + item.IsPublic);

输出

A  |  System.String
**************
A | System.String
B | System.String
**************
C | System.String | False | True
**************
<A>k__BackingField | System.String | True | False
<B>k__BackingField | System.String | True | False
C | System.String | False | True
D | System.String | False | False
E | System.String | False | False
G | System.String | True | False

GetProperties()GetFields() 都只能获取到 public 类型的属性/字段;

GetRuntimeProperties()GetRuntimeFields() ,能够获取所有的属性/字段;

还有一个重要的地方,GetRuntimeFields() 获取到了 <A>k__BackingField<B>k__BackingField,这是因为 {get;set;}这样的属性,C# 会默认生成一个字段给他。

1.2.4 方法

通过 GetMethod()GetMethods() 可以获取到类型的 MethodInfo ,表示方法信息;

MethodInfoConstructorInfo 非常相似,示例如下

            Type type = typeof(System.IO.File);
MethodInfo[] list = type.GetMethods();
foreach (var item in list)
{
Console.WriteLine(item.Name + " | " + item.IsStatic + " | " + item.IsPublic);
ParameterInfo[] parms = item.GetParameters();
foreach (var itemNode in parms)
{
Console.WriteLine(itemNode.Name + " | " + itemNode.ParameterType + " | " + itemNode.DefaultValue);
}
Console.WriteLine("***********");
}

输出

OpenText   |   True   |   True
path | System.String |
***********
CreateText | True | True
path | System.String |
***********
AppendText | True | True
path | System.String |
***********
Copy | True | True
sourceFileName | System.String |
destFileName | System.String |
... ...

参考资料地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.methodinfo?view=netcore-3.1

1.2.5 事件

使用 GetEvent()GetEvents() 可以获取类型的事件列表,返回 EventInfo / EventInfo[] 类型。

创建一个类型

    public class MyClass
{
public delegate void Test(int a,int b);
public event Test TestHandler;
}

打印

            Type type = typeof(MyClass);
EventInfo[] list = type.GetEvents();
foreach (var item in list)
{
Console.WriteLine(item.Name + " | " + item.EventHandlerType);
}

输出

TestHandler   |   Mytest.MyClass+Test

1.2.6 成员

使用 GetMember()GetMembers() 获取类型的成员,返回 MemberInfo / MemberInfo[] 类型。

简单来说,就是以上构造函数、属性、字段等的无差别集合体。

创建一个类型

    public class MyClass
{
public delegate void Test(int a, int b);
public event Test TestHandler; public MyClass(int a) { } public MyClass(int a, int b) { } public void TestMetod()
{
}
}

打印

            Type type = typeof(MyClass);
MemberInfo[] list = type.GetMembers();
foreach (var item in list)
{
Console.WriteLine(item.Name + " | " + item.MemberType);
}

输出

add_TestHandler   |   Method
remove_TestHandler | Method
TestMetod | Method
GetType | Method
ToString | Method
Equals | Method
GetHashCode | Method
.ctor | Constructor
.ctor | Constructor
TestHandler | Event
Test | NestedType

此文仅授权《NCC 开源社区》订阅号发布

C#反射与特性(三):反射类型的成员的更多相关文章

  1. C#反射与特性(五):类型成员操作

    目录 1,MemberInfo 1.1 练习-获取类型的成员以及输出信息 1.2 MemberType 枚举 1.3 MemberInfo 获取成员方法并且调用 1.4 获取继承中方法的信息(Decl ...

  2. C#4.0图解教程 - 第24章 反射和特性 - 1.反射

    24.1 元数据和反射 有关程序及类型的数据被成为 元数据.他们保存在程序集中. 程序运行时,可以查看其他程序集或其本身的元数据.一个运行的程序查看本身元数据或其他程序的元数据的行为叫做 反射. 24 ...

  3. C#反射与特性(七):自定义特性以及应用

    目录 1,属性字段的赋值和读值 2,自定义特性和特性查找 2.1 特性规范和自定义特性 2.2 检索特性 3,设计一个数据验证工具 3.1 定义抽象验证特性类 3.2 实现多个自定义验证特性 3.3 ...

  4. C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web

    目录 1,编写依赖注入框架 1.1 路由索引 1.2 依赖实例化 1.3 实例化类型.依赖注入.调用方法 2,编写控制器和参数类型 2.1 编写类型 2.2 实现控制器 3,实现低配山寨 ASP.NE ...

  5. 详解C#特性和反射(三)

    类型信息(Type Information)用来表示类型声明的信息,通过抽象基类System.Type的实例存储这些信息,当使用反射时,CLR获取指定类型的Type对象,通过这个对象即可访问该类型的任 ...

  6. C#反射与特性(四):实例化类型

    目录 1,实例化类型 1.1 Activator.CreateInstance() 1.2 ConstructorInfo.Invoke() 2,实例化委托 3,实例化泛型类型 3.1 实例化泛型 3 ...

  7. .NET基础拾遗(4)委托、事件、反射与特性

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  8. 十七、C# 反射、特性和动态编程

    反射.特性和动态编程   1.访问元数据 2.成员调用 3.泛型上的反射 4.自定义特性 5.特性构造器 6.具名参数 7.预定义特性 8.动态编程   特性(attribute)是在一个程序集中插入 ...

  9. C#特性和反射

    C#特性和反射 .NET编译器的任务之一就是为所有定义和引用的类型生成元数据描述.除了程序集中标准的元数据外,.NET平台还支持特定(attribute)把更多的元数据嵌入到程序集中. .NET特性扩 ...

随机推荐

  1. PDM->OOM->C#实体类生成时,对Blob类型字段的处理

    pdm中的Blob字段生成OOM时,自动变成了string类型,再生成实体类时也是string 如何将oom中对应的blob字段设置为Byte[]类型,目前没找到方法, 只能通过脚本,将生成后的OOM ...

  2. oracle函数 current_date

    [功能]:返回当前会话时区中的当前日期 [参数]:没有参数,没有括号 [返回]:日期 [示例]select current_date from dual; 返回:2008-11-14

  3. @codechef - BIKE@ Chef and Bike

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 输入 n(n ≤ 22) 个点,m(m ≤ 8000) 个边.每 ...

  4. css white-space属性

    css white-space属性 规定段落中的文本不进行换行

  5. 【原生JS】动态分页样式效果

    效果图如下: html: <body> <div> <table id="btnbox"> <tbody> <tr>&l ...

  6. Python--day21--复习

    序列化模块总结: jison格式化输出: Serialize obj to a JSON formatted str.(字符串表示的json对象) Skipkeys:默认值是False,如果dict的 ...

  7. jq实现鼠标悬停高亮当前图片

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. H3C 配置Basic NAT

  9. JPA批量操作及性能比对

    假设需要批量插入10000条实体数据至数据库.如下是各个操作方法及耗时 环境Spring boot 1.JDBC(JdbcTemplate) pom.xml <dependency> &l ...

  10. chrome浏览器频繁卡死

    输入chrome:flag 把对应的GPU选项关掉 或者重装 ,从360软件管理器上装