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 类型;

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 开源社区》订阅号发布

posted @   痴者工良  阅读(3510)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示