如何:使用 MetadataLoadCoNtext 檢查元件內容

根據預設,.NET 中的反映 API 可讓開發人員檢查載入主要執行內容中的元件內容。 不過,有時候無法將元件載入執行內容,例如,因為它已針對另一個平臺或處理器架構進行編譯,或是它是 參考元件System.Reflection.MetadataLoadContextAPI 可讓您載入和檢查這類元件。 載入 至 的 MetadataLoadContext 元件只會被視為中繼資料,也就是說,您可以檢查元件中的類型,但無法執行其中所包含的任何程式碼。 不同于主要執行內容, MetadataLoadContext 不會從目前目錄自動載入相依性;而是使用傳遞給它的 自訂 MetadataAssemblyResolver 系結邏輯。

必要條件

若要使用 MetadataLoadContext ,請安裝 System.Reflection.MetadataLoadCoNtext NuGet 套件。 任何符合 .NET Standard 2.0 規範的目標架構都支援,例如 .NET Core 2.0 或 .NET Framework 4.6.1。

建立 MetadataLoadCoNtext 的 MetadataAssemblyResolver

建立 需要 MetadataLoadContext 提供 的 MetadataAssemblyResolver 實例。 提供元件的最簡單方式是使用 PathAssemblyResolver ,它會從元件路徑字串的指定集合解析元件。 除了您想要直接檢查的元件之外,此集合也應該包含所有必要的相依性。 例如,若要讀取位於外部元件的自訂屬性,您應該包含該元件或擲回例外狀況。 在大部分情況下,您應該至少包含 核心元件,也就是包含內建系統類型的元件,例如 System.Object 。 下列程式碼示範如何使用由檢查的元件和目前執行時間的核心元件所組成的集合來建立 PathAssemblyResolver

var resolver = new PathAssemblyResolver(new string[] { "ExampleAssembly.dll", typeof(object).Assembly.Location });

如果您需要存取所有 BCL 類型,您可以在集合中包含所有執行時間元件。 下列程式碼示範如何使用由檢查的元件和目前執行時間的所有元件所組成的集合來建立 PathAssemblyResolver

// Get the array of runtime assemblies.
string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");

// Create the list of assembly paths consisting of runtime assemblies and the inspected assembly.
var paths = new List<string>(runtimeAssemblies);
paths.Add("ExampleAssembly.dll");

// Create PathAssemblyResolver that can resolve assemblies using the created list.
var resolver = new PathAssemblyResolver(paths);

建立 MetadataLoadCoNtext

若要建立 MetadataLoadContext ,請叫用其建構函 MetadataLoadContext(MetadataAssemblyResolver, String) 式,並將先前建立 MetadataAssemblyResolver 的 傳遞為第一個參數,並將核心元件名稱傳遞為第二個參數。 您可以省略核心元件名稱,在此情況下,建構函式會嘗試使用預設名稱:「mscorlib」、「System.Runtime」 或 「netstandard」。

建立內容之後,您可以使用 之類的 LoadFromAssemblyPath 方法來將元件載入其中。 您可以在載入的元件上使用所有反映 API,但涉及程式碼執行的專案除外。 方法 GetCustomAttributes 確實涉及建構函式的執行,因此當您需要檢查 中的 MetadataLoadContext 自訂屬性時,請改用 GetCustomAttributesData 方法。

下列程式碼範例會 MetadataLoadContext 建立 、將元件載入其中,並將元件屬性輸出至主控台:

var mlc = new MetadataLoadContext(resolver);

using (mlc)
{
    // Load assembly into MetadataLoadContext.
    Assembly assembly = mlc.LoadFromAssemblyPath("ExampleAssembly.dll");
    AssemblyName name = assembly.GetName();

    // Print assembly attribute information.
    Console.WriteLine($"{name.Name} has following attributes: ");

    foreach (CustomAttributeData attr in assembly.GetCustomAttributesData())
    {
        try
        {
            Console.WriteLine(attr.AttributeType);
        }
        catch (FileNotFoundException ex)
        {
            // We are missing the required dependency assembly.
            Console.WriteLine($"Error while getting attribute type: {ex.Message}");
        }
    }
}

如果您需要測試 中的 MetadataLoadContext 類型是否相等或可指派性,請只使用載入至該內容的類型物件。 MetadataLoadContext不支援混合類型與執行時間類型。 例如,請考慮 中的 MetadataLoadContext 類型 testedType 。 如果您需要測試是否可以從中指派另一個類型,請勿使用類似 的程式 typeof(MyType).IsAssignableFrom(testedType) 代碼。 請改用如下的程式碼:

Assembly matchAssembly = mlc.LoadFromAssemblyPath(typeof(MyType).Assembly.Location);
Type matchType = assembly.GetType(typeof(MyType).FullName!)!;

if (matchType.IsAssignableFrom(testedType))
{
    Console.WriteLine($"{nameof(matchType)} is assignable from {nameof(testedType)}");
}

範例

如需完整的程式碼範例,請參閱 使用 MetadataLoadCoNtext 檢查元件內容範例