重新導向組件版本
注意
本文專屬於 .NET Framework。 它不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。
您可以將編譯時間系結參考重新導向至 .NET Framework 元件、第三方元件或您自己的應用程式元件。 您可以透過許多方式,將應用程式重新導向至使用不同的元件版本:透過發行者原則、透過應用程式組態檔,或透過計算機組態檔。 本文討論元件系結在 .NET Framework 中的運作方式,以及如何進行設定。
提示
本文專屬於 .NET Framework 應用程式。 如需了解 .NET 5+(和 .NET Core)中組件載入的相關信息,請參閱 .NET 中的相依性載入。
元件統一和預設系結
.NET Framework 元件的系結有時會透過稱為 元件統一的程式重新導向。 .NET Framework 是由 Common Language Runtime 版本和組成類型連結庫的大約二十幾個 .NET Framework 元件所組成。 運行時間會將這些 .NET Framework 元件視為單一單位。 根據預設,當應用程式啟動時,執行階段運行的程式碼中對類型的所有參考,將會被引導至與程式中載入的執行階段具有相同版本號的 .NET Framework 組件。 此模型所發生的重新導向是運行時間的預設行為。
例如,如果您的應用程式參考 System.XML 命名空間中的類型,而且是使用 .NET Framework 4.5 所建置,它就會包含隨附於執行階段 4.5 版之 System.XML 元件的靜態參考。 如果您想要將系結參考重新導向至 .NET Framework 4 隨附的System.XML元件,您可以將重新導向資訊放在應用程式元件。 統一 .NET Framework 元件組態檔中的系結重新導向會取消該元件的統一。
此外,如果有多個版本可用,您可能希望手動重新導向第三方組件的元件繫結。
提示
如果您更新應用程式間接參考的 NuGet 套件,並開始看到新的錯誤,例如 FileLoadException
、MissingMethodException
、TypeLoadException
或 FileNotFoundException
,您可能需要啟用自動系結重新導向,或手動新增系結重新導向。 更新 NuGet 套件時,這是一般情況,而且是針對舊版相依性建置某些套件的結果。 下列應用程式組態檔摘要會新增 System.Memory 套件的系結重新導向:
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
使用發行者策略重新導向版本
元件的供應商可以藉由將發行者政策檔案包含在新的元件中,將應用程式導向至較新版本的元件。 位於全域程式集緩存中的發行者原則檔案包含元件重新導向設定。
每一個 主要版本和.次要 版本的組件都有自己的發行者政策文件。 例如,從 2.0.2.222 版重新導向至 2.0.3.000 版,以及從 2.0.2.321 版重新導向至 2.0.3.000 版,兩者都進入相同的檔案,因為它們與 2.0 版相關聯。 不過,從 3.0.0.999 版重新導向至 4.0.0.000 版的重新導向會進入 3.0.999 版的檔案。 .NET Framework 的每個主要版本都有自己的發行者原則檔案。
如果某個元件的發行者策略檔案存在,執行階段會在檢查該元件的資訊清單和應用程式組態檔之後檢查此檔案。 只有在新元件與重新導向的元件向後相容時,廠商才應該使用發行者策略檔案。
您可以在應用程式組態檔中指定設定,以略過應用程式的發行者原則,如 略過發行者原則 一節所述。
在應用層級重新導向版本
透過應用程式組態檔變更應用程式的系結行為有幾個不同技術:您可以 手動編輯檔案、您可以 依賴自動系結重新導向,或透過略過發行者原則 來指定系結行為。
手動編輯應用程式組態檔
您可以手動編輯應用程式組態檔來解決元件問題。 例如,如果廠商在不提供發行者原則的情況下發行您應用程式使用的較新版本元件(因為它們不保證回溯相容性),您可以指示應用程式使用較新版本的元件,方法是將元件系結資訊放在應用程式的組態檔中,如下所示。
<dependentAssembly>
<assemblyIdentity name="someAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="en-us" />
<bindingRedirect oldVersion="7.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
依賴自動系結重新導向
當您在 Visual Studio 中建立以 .NET Framework 4.5.1 或更新版本為目標的桌面應用程式時,應用程式會使用自動系結重新導向。 這表示,如果兩個元件參考相同強名稱元件的不同版本,運行時間會自動在輸出應用程式元件 (app.config) 檔案中將系結重新導向新增至較新版本的元件。 此重新導向會覆蓋其他情況下可能發生的組件合併。 來源 app.config 檔案未修改。 例如,假設您的應用程式直接參考頻外 .NET Framework 元件,但使用以舊版相同元件為目標的第三方連結庫。 當您編譯應用程式時,輸出應用程式組態檔會修改為包含系結重新導向至較新版本的元件。
如果您建立 Web 應用程式,您會收到有關係結衝突的建置警告,這反過來又可讓您選擇將必要的系結重新導向新增至來源 Web 組態檔。
如果您在編譯時期手動將系結重新導向新增至來源 app.config 檔案,Visual Studio 會嘗試根據您新增的系結重新導向來統一元件。 例如,假設您要為元件插入下列繫結重新導向:
<bindingRedirect oldVersion="3.0.0.0" newVersion="2.0.0.0" />
如果應用程式中的另一個專案參考相同元件的 1.0.0.0 版,則自動組件繫結重新導向會將以下項目新增至輸出 app.config 檔案,以讓應用程式統一至此元件的 2.0.0.0 版。
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
如果您的應用程式以舊版 .NET Framework 為目標,您可以啟用自動繫結重新導向。 您可以在任何元件的 app.config 檔案中提供系結重新導向資訊,或關閉系結重新導向功能,以覆寫此默認行為。 如需如何開啟或關閉此功能的詳細資訊,請參閱 如何:啟用和停用自動繫結重新導向。
繞過發行者政策
如有必要,您可以在應用程式組態檔中覆寫發行者原則。 例如,宣稱回溯相容的元件新版本仍然可能導致應用程式出錯。 如果您想要略過發行者原則,請將 <publisherPolicy> 元素新增至應用程式組態檔中的 <dependentAssembly> 元素,並將 apply
屬性設定為 no
,這會覆寫任何先前的 yes
設定。
<publisherPolicy apply="no" />
略過發行者原則,讓您的應用程式持續為使用者執行,但請確定您向元件廠商回報問題。 如果元件有發行者原則檔案,廠商應該確定元件回溯相容,且用戶端可以盡可能使用新版本。
重新導向其他元件所使用的測試、外掛程式或連結庫版本
針對測試,您應該產生 .dll.config 檔案。 載入測試時,大部分現有的單元測試架構都會接受這些檔案。
不過,外掛程式可能會接受 .dll.config 檔案,但也可能不接受。 重新導向的唯一萬無一失的機制,就是在建立 AppDomain 時提供 bindingRedirects
。
您可以使用 AssemblyResolve 事件處理程式來嘗試解決此問題,但這無法運作,因為這些處理程式只會在失敗的負載上呼叫。 如果元件載入成功,可能是因為已由另一個元件或主機載入,或存在於 GAC 中,則不會呼叫 AssemblyResolve
處理程式。
在機器層級重新導向版本
電腦管理員可能會在某些少數情況下,要求電腦上的所有應用程式使用某個特定版本的元件。 例如,特定版本可能會修正安全性漏洞。 如果在計算機組態檔中重新導向元件,稱為 machine.config,則會將使用該舊版本之計算機上的所有應用程式導向為使用新版本。 計算機組態檔會覆寫應用程式組態檔和發行者原則檔案。 這個 machine.config 檔案位於32位電腦的 %windir%\Microsoft.NET\Framework[version]\config\machine.config,或64位電腦的 %windir%\Microsoft.NET\Framework64[version]\config\machine.config。
在組態檔中指定元件系結
您可以使用相同的 XML 格式來指定系結重新導向,無論是在應用程式組態檔、計算機組態檔還是發行者原則檔中。 若要將某個元件版本重新導向至另一個元件版本,請使用 <bindingRedirect> 元素。
oldVersion
屬性可以指定單一元件版本或版本範圍。
newVersion
屬性應該指定單一版本。 例如,<bindingRedirect oldVersion="1.1.0.0-1.2.0.0" newVersion="2.0.0.0"/>
指定運行時間應該使用 2.0.0.0 版,而不是 1.1.0.0 和 1.2.0.0 之間的元件版本。
下列程式代碼範例示範各種系結重新導向案例。 此範例會針對 myAssembly
指定版本範圍的重新導向,並針對 mySecondAssembly
指定單一系結重新導向。 此範例也指出發行者原則文件不會覆寫 myThirdAssembly
的系結重新導向。
若要系結組件,您必須在 <assemblyBinding> 標記中的 xmlns
屬性中指定字串 "urn:schemas-microsoft-com:asm.v1"。
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="myAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="en-us" />
<!-- Assembly versions can be redirected in app,
publisher policy, or machine configuration files. -->
<bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="mySecondAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="en-us" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="myThirdAssembly"
publicKeyToken="32ab4ba45e0a69a1"
culture="en-us" />
<!-- Publisher policy can be set only in the app
configuration file. -->
<publisherPolicy apply="no" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
將組件綁定限制為特定版本
您可以在應用程式組態檔中的 <assemblyBinding> 元素上使用 appliesTo
屬性,將元件系結參考重新導向至特定版本的 .NET Framework。 這個選擇性屬性會使用 .NET Framework 版本號碼來指出其適用的版本。 如果未指定 appliesTo
屬性,<assemblyBinding> 專案會套用至所有 .NET Framework 版本。
例如,若要重新導向 .NET Framework 3.5 組件的組件繫結,您會在應用程式組態檔中包含下列 XML 代碼。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"
appliesTo="v3.5">
<dependentAssembly>
<!-- assembly information goes here -->
</dependentAssembly>
</assemblyBinding>
</runtime>
您應該依版本順序輸入重新導向資訊。 例如,輸入 .NET Framework 3.5 元件的元件系結重新導向資訊,接下來輸入 .NET Framework 4.5 元件的資訊。 最後,輸入未使用 appliesTo
屬性之任何 .NET Framework 元件重新導向的元件系結重新導向資訊,因此適用於所有版本的 .NET Framework。 如果重新導向發生衝突,則會使用組態檔中的第一個相符重新導向語句。
例如,若要將一個參考重新導向至 .NET Framework 3.5 元件,另一個參考重新導向至 .NET Framework 4 元件,請使用下列偽代碼所示的模式。
<assemblyBinding xmlns="..." appliesTo="v3.5 ">
<!--.NET Framework version 3.5 redirects here -->
</assemblyBinding>
<assemblyBinding xmlns="..." appliesTo="v4.0.30319">
<!--.NET Framework version 4.0 redirects here -->
</assemblyBinding>
<assemblyBinding xmlns="...">
<!-- redirects meant for all versions of the runtime -->
</assemblyBinding>