詳解 .NET 反射中的 BindingFlags 以及常用的 BindingFlags 使用方式
- 2020 年 2 月 10 日
- 筆記
使用 .NET 的反射 API 時,通常會要求我們傳入一個 BindingFlags
參數用於指定反射查找的範圍。不過如果對反射不熟的話,第一次寫反射很容易寫錯導致找不到需要的類型成員。
本文介紹 BindingFlags
中的各個枚舉標記的含義、用途,以及常用的組合使用方式。
所有的 BindingFlags
默認值
// 默認值 Default
查找
這些標記用於反射的時候查找類型成員:
// 表示查找的時候,需要忽略大小寫。 IgnoreCase // 僅查找此特定類型中聲明的成員,而不會包括這個類繼承得到的成員。 DeclaredOnly // 僅查找類型中的實例成員。 Instance // 僅查找類型中的靜態成員。 Static // 僅查找類型中的公共成員。 Public // 僅查找類型中的非公共成員(internal protected private) NonPublic // 會查找此特定類型繼承樹上得到的靜態成員。但僅繼承公共(public)靜態成員和受保護(protected)靜態成員;不包含私有靜態成員,也不包含嵌套類型。 FlattenHierarchy
調用
這些標記用於為 InvokeMember
方法提供參數,告知應該如何反射調用一個方法:
// 調用方法。 InvokeMethod // 創建實例。 CreateInstance // 獲取欄位的值。 GetField // 設置欄位的值。 SetField // 獲取屬性的值。 GetProperty // 設置屬性的值。 SetProperty
其他
接下來下面的部分就不是那麼常用的了。
這些標記用於為 InvokeMember
方法提供參數,但是僅在調用一個 COM 組件的時候才應該使用:
PutDispProperty PutRefDispProperty
ExactBinding SuppressChangeType
OptionalParamBinding
下面是一些雜項……
// 忽略返回值(在 COM 組件的互操作中使用) IgnoreReturn // 反射調用方法時如果出現了異常,通常反射會用 TargetInvocationException 包裝這個異常。 // 此標記用于禁止把異常包裝到 TargetInvocationException 中。 DoNotWrapExceptions
你可能會有的疑問
- 如果 A 程式集對 B 程式集內部可見(
InternalsVisibleTo("B")
),那麼 B 在反射查找 A 的時候,internal
成員的查找應該使用Public
還是NonPublic
標記呢?- 依然是
NonPublic
標記。 - 因為反射的是程式集的元數據,這是靜態的數據,跟運行時狀態是無關的。
- 依然是
常用的組合
從上面的解釋中可以發現,這個類型的設計其實是有問題的,不符合單一職責原則。所以我們會在不同的使用場景下使用不同區域的組合。
查找,也就是獲取一個類型中的欄位、屬性、方法等的時候使用的。
拿到所有成員:
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance
實際上 RuntimeReflectionExtensions.Everything
屬性就是這麼寫的。
拿到公有的實例成員:
BindingFlags.Public | BindingFlags.Instance
附 BindingFlags 的源碼
[Flags] public enum BindingFlags { // NOTES: We have lookup masks defined in RuntimeType and Activator. If we // change the lookup values then these masks may need to change also. // a place holder for no flag specifed Default = 0x00, // These flags indicate what to search for when binding IgnoreCase = 0x01, // Ignore the case of Names while searching DeclaredOnly = 0x02, // Only look at the members declared on the Type Instance = 0x04, // Include Instance members in search Static = 0x08, // Include Static members in search Public = 0x10, // Include Public members in search NonPublic = 0x20, // Include Non-Public members in search FlattenHierarchy = 0x40, // Rollup the statics into the class. // These flags are used by InvokeMember to determine // what type of member we are trying to Invoke. // BindingAccess = 0xFF00; InvokeMethod = 0x0100, CreateInstance = 0x0200, GetField = 0x0400, SetField = 0x0800, GetProperty = 0x1000, SetProperty = 0x2000, // These flags are also used by InvokeMember but they should only // be used when calling InvokeMember on a COM object. PutDispProperty = 0x4000, PutRefDispProperty = 0x8000, ExactBinding = 0x010000, // Bind with Exact Type matching, No Change type SuppressChangeType = 0x020000, // DefaultValueBinding will return the set of methods having ArgCount or // more parameters. This is used for default values, etc. OptionalParamBinding = 0x040000, // These are a couple of misc attributes used IgnoreReturn = 0x01000000, // This is used in COM Interop DoNotWrapExceptions = 0x02000000, // Disables wrapping exceptions in TargetInvocationException }
參考資料
本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名 呂毅 (包含鏈接: https://blog.walterlv.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請 與我聯繫 ([email protected]) 。