C#反射與特性(三):反射類型的成員

上一篇文章中,介紹如何獲取 Type 類型,Type 類型是反射的基礎。html

本篇文章中,將使用 Type 去獲取成員信息,經過打印出反射獲取到的信息,爲後續操做反射打好基礎。api


目錄ide



1,獲取類型的信息

咱們經常能夠看到 函數、方法這兩個詞,不少人對此進行了混用。函數

方法,就是 public void Test(){} 這樣的形式;spa

函數,指具備肯定命名的、而且能夠經過名稱調用的代碼,屬性、字段、方法、委託、事件等;code

只要可以經過肯定的名稱調用(使用)的代碼塊,就是函數;而方法就是 返回值、名稱、參數等組成的代碼塊;htm

要操做反射,首先要獲取到 類型 的反射信息,而類型的 Type ,與如下多種類型密切相關。blog

類型 說明
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("**************");

            IEnumerablelistB = 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("**************");

            IEnumerablelistD = 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
**************k__BackingField  |  System.String    |   True    |   Falsek__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() 獲取到了 k__BackingFieldk__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 開源社區》訂閱號發佈

相關文章
相關標籤/搜索