C#反射与特性(三):反射类型的成员
上一篇文章中,介绍如何获取 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 类型;
ConstructorInfo 的 GetParameter() 或 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 ,表示方法信息;
MethodInfo 跟 ConstructorInfo 非常相似,示例如下
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#反射与特性(三):反射类型的成员的更多相关文章
- C#反射与特性(五):类型成员操作
目录 1,MemberInfo 1.1 练习-获取类型的成员以及输出信息 1.2 MemberType 枚举 1.3 MemberInfo 获取成员方法并且调用 1.4 获取继承中方法的信息(Decl ...
- C#4.0图解教程 - 第24章 反射和特性 - 1.反射
24.1 元数据和反射 有关程序及类型的数据被成为 元数据.他们保存在程序集中. 程序运行时,可以查看其他程序集或其本身的元数据.一个运行的程序查看本身元数据或其他程序的元数据的行为叫做 反射. 24 ...
- C#反射与特性(七):自定义特性以及应用
目录 1,属性字段的赋值和读值 2,自定义特性和特性查找 2.1 特性规范和自定义特性 2.2 检索特性 3,设计一个数据验证工具 3.1 定义抽象验证特性类 3.2 实现多个自定义验证特性 3.3 ...
- C#反射与特性(六):设计一个仿ASP.NETCore依赖注入Web
目录 1,编写依赖注入框架 1.1 路由索引 1.2 依赖实例化 1.3 实例化类型.依赖注入.调用方法 2,编写控制器和参数类型 2.1 编写类型 2.2 实现控制器 3,实现低配山寨 ASP.NE ...
- 详解C#特性和反射(三)
类型信息(Type Information)用来表示类型声明的信息,通过抽象基类System.Type的实例存储这些信息,当使用反射时,CLR获取指定类型的Type对象,通过这个对象即可访问该类型的任 ...
- C#反射与特性(四):实例化类型
目录 1,实例化类型 1.1 Activator.CreateInstance() 1.2 ConstructorInfo.Invoke() 2,实例化委托 3,实例化泛型类型 3.1 实例化泛型 3 ...
- .NET基础拾遗(4)委托、事件、反射与特性
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- 十七、C# 反射、特性和动态编程
反射.特性和动态编程 1.访问元数据 2.成员调用 3.泛型上的反射 4.自定义特性 5.特性构造器 6.具名参数 7.预定义特性 8.动态编程 特性(attribute)是在一个程序集中插入 ...
- C#特性和反射
C#特性和反射 .NET编译器的任务之一就是为所有定义和引用的类型生成元数据描述.除了程序集中标准的元数据外,.NET平台还支持特定(attribute)把更多的元数据嵌入到程序集中. .NET特性扩 ...
随机推荐
- 浮动,定位,flex布局
什么是文档流 英文原文是:Normal flow. In CSS 2.1, normal flow includes block formatting of block-level boxes, in ...
- Python--day62--删除出版社
删除成出版社关键代码:
- tf.variable_scope 参数
最近在看TensorFlow的变量管理,发现很多代码中tf.variable_scope()参数的数量及意义还不太清楚,特此记录: def __init__(self, name_or_scope, ...
- C# 标准性能测试
经常我写一个类,作为一个工具类,小伙伴会问我这个类的性能,这时我就需要一个标准的工具进行测试. 本文告诉大家如何使用 benchmarkdotnet 做测试. 现在在 github 提交代码,如果有小 ...
- js(一) 三大事件 实现注册验证
ps:小声比比,为什么一周多没更,因为js真的好难啊. 上一周做了一整周的jsp+sevlet+mysql做了一个MVC模式的最基本的新闻系统源码会有空搞出来的 好累 好多的. 三大事件 (鼠标事件. ...
- UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)
题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...
- Scheduler
先看看文档对于Scheduler的作用介绍 https://code4craft.gitbooks.io/webmagic-in-action/content/zh/posts/ch1-overvie ...
- 改善Azure App Service托管应用程序性能的几个技巧
本文介绍了几个技巧,这些技巧可以改善Azure App Service托管应用程序的性能.其中一些技巧是你现在就可以进行的配置变更, 而其他技巧则可能需要对应用程序进行一些重新设计和重构. 开发者都希 ...
- 性能测试基础-SOCKET协议用例
1.首先在进行性能测试的时候,我们要了解软件的通信协议是什么,我们使用什么协议,如何去模拟.SOCKET协议主要应用于在C/S模式的系统. 作者本人已当初做过的C/S架构的系统做的脚本录制,在上面做脚 ...
- 2018-2-13-手机1520-win8.1升级win10
title author date CreateTime categories 手机1520 win8.1升级win10 lindexi 2018-2-13 17:23:3 +0800 2018-2- ...