分享方式:


受控組件載入演算法

透過演算法定位及載入受控組件分為幾個不同的階段。

除了附屬組件和 WinRT 組件之外,所有受控組件都使用相同的演算法。

何時會載入受控組件?

最常用來觸發受控組件載入的方法是靜態組件參考。 每當程式碼使用其他組件中定義的類型時,編譯器就會插入這些參考。 這些階件會在執行階段需要時載入 (load-by-name)。 載入靜態組件參考的確切時間不確定, 會隨執行階段版本及最佳化 (例如內嵌) 的影響而異。

直接使用下列 API 也會觸發載入:

API 描述 Active AssemblyLoadContext
AssemblyLoadContext.LoadFromAssemblyName Load-by-name this 執行個體。
AssemblyLoadContext.LoadFromAssemblyPath
AssemblyLoadContext.LoadFromNativeImagePath
從路徑載入。 this 執行個體。
AssemblyLoadContext.LoadFromStream 從物件載入。 this 執行個體。
Assembly.LoadFile 從新 AssemblyLoadContext 執行個體中的路徑載入 AssemblyLoadContext 執行個體。
Assembly.LoadFrom AssemblyLoadContext.Default 執行個體中的路徑載入。
新增 AppDomain.AssemblyResolve 處理常式。 此處理常式會從其目錄載入組件的相依性。
AssemblyLoadContext.Default 執行個體。
Assembly.Load(AssemblyName)
Assembly.Load(String)
Assembly.LoadWithPartialName
Load-by-name. 從呼叫端推斷。
優先使用 AssemblyLoadContext 方法。
Assembly.Load(Byte[])
Assembly.Load(Byte[], Byte[])
從新 AssemblyLoadContext 執行個體中的物件載入。 AssemblyLoadContext 執行個體。
Type.GetType(String)
Type.GetType(String, Boolean)
Type.GetType(String, Boolean, Boolean)
Load-by-name. 從呼叫端推斷。
優先使用 Type.GetType 具採用 assemblyResolver 引數的方法。
Assembly.GetType 若類型 name 指定組件限定泛型型別,會觸發 Load-by-name 從呼叫端推斷。
當使用組件限定類型名稱時,會優先使用 Type.GetType
Activator.CreateInstance(String, String)
Activator.CreateInstance(String, String, Object[])
Activator.CreateInstance(String, String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[])
Load-by-name. 從呼叫端推斷。
優先使用 Activator.CreateInstance 採用 Type 引數的方法。

演算法

下列演算法描述執行階段如何載入受控組件。

  1. 決定 active AssemblyLoadContext

  2. 對於 Load-by-name 方法,active AssemblyLoadContext 會依下列優先順序載入組件:

  3. 對於其他類型的載入,active AssemblyLoadContext 會依下列優先順序載入組件:

    • 檢查其 cache-by-name
    • 從指定的路徑或原始組件物件載入。 若是新載入的組件,則會新增參考至 active AssemblyLoadContext 執行個體的 cache-by-name
  4. 無論何種情況,只要是新載入的組件,都會引發 AppDomain.AssemblyLoad 事件。