C#反射与特性(三):反射类型的成员

简介: C#反射与特性(三):反射类型的成员

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

相关文章
|
1月前
|
C#
C#学习相关系列之数据类型类的三大特性(二)
C#学习相关系列之数据类型类的三大特性(二)
|
3月前
|
编译器 C# 开发者
C# 11.0中的新特性:覆盖默认接口方法
C# 11.0进一步增强了接口的灵活性,引入了覆盖默认接口方法的能力。这一新特性允许类在实现接口时,不仅可以提供接口中未实现的方法的具体实现,还可以覆盖接口中定义的默认方法实现。本文将详细介绍C# 11.0中接口默认方法覆盖的工作原理、使用场景及其对现有代码的影响,帮助开发者更好地理解和应用这一新功能。
|
3月前
|
存储 安全 编译器
C# 11.0中的泛型属性:类型安全的新篇章
【1月更文挑战第23天】C# 11.0引入了泛型属性的概念,这一新特性为开发者提供了更高级别的类型安全性和灵活性。本文将详细探讨C# 11.0中泛型属性的工作原理、使用场景以及它们对现有编程模式的改进。通过深入了解泛型属性,开发者将能够编写更加健壮、可维护的代码,并充分利用C#语言的最新发展。
|
3月前
|
编译器 C# 开发者
C# 9.0中的顶级语句:简化程序入口的新特性
【1月更文挑战第13天】本文介绍了C# 9.0中引入的顶级语句(Top-level statements)特性,该特性允许开发者在不使用传统的类和方法结构的情况下编写简洁的程序入口代码。文章详细阐述了顶级语句的语法、使用场景以及与传统程序结构的区别,并通过示例代码展示了其在实际应用中的便捷性。
|
1月前
|
存储 C# 开发者
C#变量类型
C#变量类型
19 0
|
3月前
|
开发框架 .NET 编译器
C# 9.0中的目标类型新表达式:类型推断的又一进步
【1月更文挑战第16天】C# 9.0引入了目标类型新表达式,这是类型推断功能的一个重要扩展。通过目标类型新表达式,开发者在创建对象时可以省略类型名称,编译器会根据上下文自动推断所需类型。这一特性不仅简化了代码编写,还提高了代码的可读性和维护性。本文将详细介绍目标类型新表达式的语法、使用场景及其对C#编程的影响。
|
3月前
|
开发框架 .NET Java
ASP.NET Core高级编程--C#基本特性(一)
本文章简略介绍C#的部分特性
|
3月前
|
存储 C# 容器
掌握 C# 变量:在代码中声明、初始化和使用不同类型的综合指南
变量是用于存储数据值的容器。 在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99 char - 存储单个字符,如 'a' 或 'B'。Char 值用单引号括起来 string - 存储文本,如 "Hello World"。String 值用双引号括起来 bool - 存储具有两个状态的值:true 或 false
39 2
|
3月前
|
设计模式 C#
C#反射机制实现开闭原则的简单工厂模式
C#反射机制实现开闭原则的简单工厂模式
18 0
|
3月前
|
存储 安全 算法
C# 泛型:类型参数化的强大工具
【1月更文挑战第7天】本文将深入探讨C#语言中的泛型编程,包括泛型的定义、用途、优势以及实际应用。通过类型参数化,泛型允许开发者编写更加灵活且可重用的代码,同时提高程序的类型安全性和性能。本文将通过示例代码和详细解释,帮助读者更好地理解泛型在C#中的重要性和实用性。