上一篇文章中,介绍如何获取 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. @codechef - TREEPATH@ Decompose the Tree

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵无根树,每个节点上都写了一个整数. 你的任务就是统计有多 ...

  2. 理解虚拟主机与VPS,云服务器CVM与云服务器ECS的区别

    1.理解虚拟主机与VPS的区别:VPS与虚拟主机的区别 2.理解云服务器CVM与云服务器ECS的区别:云服务器CVM与云服务器ECS的区别 3.锐速安装一键包

  3. ThinkPHP商城实战

    ThinkPHP3.2.3商城实战教程,需要的联系我,QQ:1844912514 千万级php电商秒杀项目实战  ,需要的联系我,QQ:1844912514

  4. Ubuntu16.04.3深度学习环境搭建

    依赖 pip3 install pillow 安装numpy相关sudo apt-get install python-numpy python-scipy python-matplotlib ipy ...

  5. SQL,范式,事务

    数据库范式: 构造数据库必须遵循一定的规则.在关系数据库中,这种规则就是范式. 范式是符合某一种级别的关系模式的集合.数据库中的关系必须满足一定的要求,即满足不同的范式. 满足最低要求的范式是第一范式 ...

  6. Spring的注解@Qualifier注解

    @Qualifier注解了,qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,我们修改调用代码,添加@Qualifier注解,需要注意的是@Qualifier的参数名称 ...

  7. 简单的Spring Batch示例

    使用Spring Batch做为批处理框架,可以完成常规的数据量不是特别大的离线计算. 现在写一个简单的入门版示例. 这里默认大家已经掌握了Spring Batch的基本知识,示例只是为了快速上手实践 ...

  8. thinkcmf,thinksns,thinkphp,onethink三者是什么关系?

    thinksns 是基于tp的老版本二开的 thinkcmf 是网友基于tp开发的cmf thinkphp 是顶想的框架 onethink 是顶想基于tp开发的cmf 官方目前只有ThinkPHP和O ...

  9. P1101 走迷宫一

    题目描述 大魔王抓住了爱丽丝,将她丢进了一口枯井中,并堵住了井口. 爱丽丝在井底发现了一张地图,他发现他现在身处一个迷宫当中,从地图中可以发现,迷宫是一个N*M的矩形,爱丽丝身处迷宫的左上角,唯一的出 ...

  10. H3C IPv6邻居发现协议