僅反射載入(ReflectionOnlyLoadFrom)的 .NET 程式集,如何反射獲取它的 Attribute 元數據呢?
- 2020 年 2 月 10 日
- 筆記
平時我們獲取一個程式集或者類型的 Attribute
是非常輕鬆的,只需要通過 GetCustomAttribute
方法就能拿到實例然後獲取其中的值。但是,有時我們僅為反射載入一些程式集的時候,獲取這些元數據就不那麼簡單了,因為我們沒有載入目標程式集中的類型。
本文介紹如何為僅反射載入的程式集讀取 Attribute 元數據資訊。
僅反射載入一個程式集
使用 ReflectionOnlyLoadFrom
可以僅以反射的方式載入一個程式集。
var extensionFilePath = @"C:UserswalterlvDesktopWalterlv.Extension.dll"; var assembly = Assembly.ReflectionOnlyLoadFrom(extensionFilePath);
獲取程式集的 Attribute(例如獲取程式集版本號)
Assembly.GetCustomAttributesData()
得到的是一個 CustomAttributeData
的列表,而這個列表中的每一項都與普通反射中拿到的特性集合不同,這裡拿到的只是特性的資訊(以下循環中的 data
變數)。
CustomAttributeData
中有 AttributeType
屬性,雖然此屬性是 Type
類型的,但是實際上它只會是 RuntimeType
類型,而不會是真實的 Attribute
的類型(因為不能保證宿主程式域中已經載入了那個類型)。
var customAttributesData = assembly.GetCustomAttributesData(); foreach (CustomAttributeData data in customAttributesData) { // 這裡可以針對每一個拿到的慝的資訊進行操作。 }
比如我們要獲取這個程式集的版本號,正常我們寫 assembly.GetCustomAttribute<AssemblyFileVersionAttribute>().Version
,但是這裡我們無法生成 AssemblyFileVersionAttribute
的實例,我們只能這麼寫:
var versionString = assembly.GetCustomAttributesData() .FirstOrDefault(x => x.AttributeType.FullName == typeof(AssemblyFileVersionAttribute).FullName) ?.ConstructorArguments[0].Value as string ?? "0.0"; var version = new Version(versionString);
程式碼解讀是這樣的:
- 我們從拿到的所有的
Attribute
元數據中找到第一個名稱與AssemblyFileVersionAttribute
相同的數據; - 從數據的構造函數參數中找到傳入的參數值,而這個值就是我們定義
AssemblyFileVersionAttribute
時傳入的參數的實際值。
因為我們知道 AssemblyFileVersionAttribute
的構造函數只有一個,所以我們確信可以從第一個參數中拿到我們想要的值。
順便一提,我們使用 AssemblyFileVersionAttribute
而不是使用 AssemblyVersionAttribute
是因為使用 .NET Core 新格式(基於 Microsoft.NET.Sdk)編譯出來的程式集默認是不帶 AssemblyVersionAttribute
的。詳見:語義版本號(Semantic Versioning) – walterlv。
參考資料
- CustomAttributeData Class (System.Reflection) – Microsoft Docs
- c# – How to get custom attributes from an assembly that is not (really) loaded – Stack Overflow
- c# – Get custom attribute data from assembly file and unlock it afterwise – Stack Overflow
本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名 呂毅 (包含鏈接: https://blog.walterlv.com ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請 與我聯繫 ([email protected]) 。