共用方式為


WPF 增益集概觀

.NET Framework 包含開發人員可用來建立支援增益集擴充性的應用程式增益集模型。 此增益集模型可讓您建立增益集,整合並擴充應用程式的功能。 在某些情況下,應用程式也需要顯示增益集提供的使用者介面。本主題說明 WPF 如何擴大 .NET Framework 增益集模型來啟用這些案例、其背後的架構、其優點及其限制。

必要條件

熟悉 .NET Framework 增益集模型是必要的。 如需詳細資訊,請參閱增益集和擴充性

增益集概觀

為避免新功能包含複雜的應用程式重新編譯和重新部署,應用程式會實作擴充性機制,讓開發人員 (第一方和第三方) 建立整合它們的其他應用程式。 支援此擴充性類型最常見的方式是使用增益集 (也稱為「附加元件」和「外掛程式」)。 公開增益集擴充性的真實世界應用程式範例包括︰

  • Internet Explorer 附加元件。

  • Windows Media Player 外掛程式。

  • Visual Studio 增益集。

例如,Windows Media Player 增益集模型讓協力廠商開發人員實作以各種方式擴充 Windows Media Player 的「外掛程式」,包括建立適用於 Windows Media Player 原本不支援之媒體格式的解碼器和編碼器 (例如 DVD、MP3)、音訊效果和面板。 每個增益集模型都是建置來公開對應用程式的獨特功能,雖然有幾個實體和行為通用所有的增益集模型。

一般增益集擴充性解決方案的三個主要實體是「合約」、「增益集」和「主應用程式」。 合約定義增益集與主應用程式整合的兩種方式︰

  • 增益集整合主應用程式所實作的功能。

  • 主應用程式公開要整合的增益集功能。

為能使用增益集,主應用程式需要在執行階段找到並載入它們。 因此,支援增益集的應用程式有下列額外的責任︰

  • 探索︰尋找遵守主應用程式所支援合約的增益集。

  • 啟用︰載入、執行及建立與增益集的通訊。

  • 隔離︰使用應用程式定義域或處理程序來建立隔離界限,保護應用程式不受增益集的潛在安全性和執行問題影響。

  • 通訊︰透過呼叫方法及傳送資料,讓增益集及主應用程式跨越隔離界限互相通訊。

  • 存留期管理︰以簡潔、可預測的方式載入和卸載應用程式定義域和處理程序 (請參閱應用程式定義域)。

  • 版本控制︰確保建立任一新版本時,主應用程式和增益集仍可通訊。

最後,開發強固的增益集模型是重要的工作。 因此,.NET Framework 可提供建置增益集模型的基礎結構。

注意

如需增益集的詳細資訊,請參閱增益集和擴充性

.NET Framework 增益集模型概觀

System.AddIn 命名空間中的 .NET Framework 增益集模型,包含一組為簡化增益集擴充性開發所設計的類型。 .NET Framework 增益集模型的基本單位是「合約」,其會定義主應用程式和增益集彼此如何通訊。 合約會向使用合約主應用程式特定「檢視」的主應用程式公開。 同樣地,合約的增益集專用「檢視」也會向增益集公開。 「配接器」用以讓主應用程式和增益集在其各自的合約檢視間進行通訊。 合約、檢視和配接器稱為區段,一組相關的區段構成「管線」。 管線是 .NET Framework 增益集模型支援探索、啟動、安全性隔離、執行隔離 (使用應用程式定義域和處理程序)、通訊、生命週期管理和版本控制的基礎。

這項支援的要點是讓開發人員建置增益集,整合主應用程式的功能。 不過,部分情況下需要主應用程式顯示增益集所提供的使用者介面。因為 .NET Framework 中每種呈現技術都有用以實作使用者介面的自有模型,所以 .NET Framework 增益集模型不支援任何特定的呈現技術。 相反地,WPF 會使用增益集的 UI 支援來擴充 .NET Framework 增益集模型。

WPF 增益集

WPF 聯合 .NET Framework 增益集模型,可讓您處理需要主應用程式從增益集顯示使用者介面的各種情況。特別是,這些案例是由 WPF 與下面兩個程式設計模型所解決︰

  1. 增益集傳回 UI。 增益集透過方法呼叫將 UI 傳回主應用程式,如合約所定義。 此案例用於下列情況︰

    • 增益集傳回的 UI 外觀相依於只存在於執行階段的資料或條件,例如動態產生的報表。

    • 增益集所提供服務的 UI 不同於可使用增益集之主應用程式的 UI。

    • 增益集主要執行主應用程式服務,並向具有 UI 的主應用程式報告狀態。

  2. 增益集為 UI。 增益集是 UI,如合約所定義。 此案例用於下列情況︰

    • 增益集不提供顯示以外的服務,例如廣告。

    • 增益集所提供服務的 UI 對可以使用該增益集的主應用程式而言很普通,例如計算機或色彩選擇器。

這些案例需要 UI 物件能在主應用程式和增益集應用程式定義域之間傳遞。 因為 .NET Framework 增益集模型仰賴應用程式定義域之間的遠端通訊,所以在其之間傳遞的物件必須可遠端處理。

可在遠端處理的物件是執行下列一或多個工作的類別執行個體︰

注意

如需建立可遠端處理之 .NET Framework 物件的詳細資訊,請參閱讓物件變成可遠端處理

WPF UI 類型不能從遠端處理。 為解決此問題,WPF 會擴充 .NET Framework 增益集模型,從主應用程式顯示增益集建立的 WPF UI。 這個支援是由 WPF 提供,並具有兩種類型:INativeHandleContract 介面,以及由 FrameworkElementAdapters 類別實作的兩個靜態方法:ContractToViewAdapterViewToContractAdapter。 概括而言,這些類型和方法的使用方式如下︰

  1. WPF 要求增益集提供的使用者介面是直接或間接衍生自 FrameworkElement 的類別,例如圖形、控制項、使用者控制項、版面配置面板和頁面。

  2. 無論合約是否宣告將在增益集與主應用程式之間傳遞 UI,其都必須宣告為 INativeHandleContract (而非 FrameworkElement),INativeHandleContract 是能夠跨隔離界限傳遞之可從遠端表示的增益集 UI。

  3. 從增益集的應用程式定義域傳遞之前,FrameworkElement 會藉由呼叫 ViewToContractAdapter 來封裝為 INativeHandleContract

  4. 傳遞至主應用程式的應用程式定義域之後,INativeHandleContract 必須藉由呼叫 ContractToViewAdapter 來重新封裝為 FrameworkElement

您需要依特定案例的情況,選擇 INativeHandleContractContractToViewAdapterViewToContractAdapter 的使用方式。 下列各節提供每個程式設計模型的詳細資料。

增益集傳回使用者介面

為使增益集將 UI 傳回至主應用程式,需要︰

  1. 您必須建立主應用程式、增益集和管線,如 .NET Framework 增益集和擴充性一文所述。

  2. 合約必須實作 IContract,而且若要傳回UI,合約必須宣告具有類型為 INativeHandleContract 之傳回值的方法。

  3. 在增益集和主應用程式間傳遞的 UI 必須直接或間接衍生自 FrameworkElement

  4. 增益集傳回的 UI 必須先從 FrameworkElement 轉換成 INativeHandleContract,才能跨越隔離界限。

  5. 因此,在跨越隔離邊界之後,傳回的 UI 必須從 INativeHandleContract 轉換成 FrameworkElement

  6. 主應用程式會顯示傳回的 FrameworkElement

如需示範如何實作會傳回 UI 的增益集範例,請參閱建立傳回 UI 的增益集

增益集是使用者介面

當增益集是 UI 時,需要︰

  1. 您必須建立主應用程式、增益集和管線,如 .NET Framework 增益集和擴充性一文所述。

  2. 增益集的合約介面必須實作 INativeHandleContract

  3. 傳遞給主應用程式的增益集必須直接或間接衍生自 FrameworkElement

  4. 在跨越隔離邊界之前,必須先將增益集從 FrameworkElement 轉換成 INativeHandleContract

  5. 在跨越隔離邊界之後,必須先將增益集從 INativeHandleContract 轉換成 FrameworkElement

  6. 主應用程式會顯示傳回的 FrameworkElement

如需示範如何實作本身即為 UI 的增益集範例,請參閱建立本身為 UI 的增益集

從增益集傳回多個 UI

增益集通常會提供多個使用者介面供主應用程式顯示。 例如,增益集是向主應用程式提供狀態資訊的 UI,也是 UI。 像這樣的增益集的實作方法是,使用增益集傳回使用者介面增益集是使用者介面模型這兩種技術的組合。

增益集和 XAML 瀏覽器應用程式

在到目前為止的範例中,主應用程式一直是已安裝的獨立應用程式。 儘管有下列額外建置和實作需求,但是 XAML 瀏覽器應用程式 (XBAP) 也可以裝載增益集︰

  • XBAP 應用程式資訊清單必須特別設定為將管線 (資料夾和組件) 和增益集組件下載至用戶端電腦的 ClickOnce 應用程式快取,和 XBAP 在相同的資料夾中。

  • 探索及載入增益集的 XBAP 程式碼必須使用 XBAP 的 ClickOnce 應用程式快取作為管線和增益集位置。

  • 如果增益集參考位於原始網站的鬆散式檔案,XBAP 必須將增益集載入特殊的安全性內容;為 XBAP 所裝載時,增益集只能參考位於主應用程式原始網站的鬆散式檔案。

下列各小節將詳細說明這些工作。

設定 ClickOnce 部署的管線和增益集

XBAP 會下載到 ClickOnce 部署快取的安全資料夾中並執行。 為了讓 XBAP 裝載增益集,管線和增益集組件也必須下載到安全資料夾。 為達到此目的,您需要設定應用程式資訊清單包含管線和增益集組件以供下載。 這在 Visual Studio 最容易完成,雖然管線和增益集組件需要位在裝載 XBAP 專案的根資料夾中,才能讓 Visual Studio 偵測管線組件。

因此,第一個步驟是設定每個管線組件和增益集組件專案的組建輸出,組建 XBAP 專案根目錄的管線和增益集組件。 下表顯示管線組件專案及增益集組件專案的組建輸出路徑,這些專案和裝載 XBAP 專案位在相同的解決方案和根資料夾中。

表 1:XBAP 裝載之管線組件的組建輸出路徑

管線組件專案 建置輸出路徑
合約 ..\HostXBAP\Contracts\
增益集檢視 ..\HostXBAP\AddInViews\
增益集端配接器 ..\HostXBAP\AddInSideAdapters\
主控件端配接器 ..\HostXBAP\HostSideAdapters\
增益集 ..\HostXBAP\AddIns\WPFAddIn1

下一步是執行下列步驟,將管線組件和增益集組件指定為 Visual Studio 的 XBAP 內容檔案︰

  1. 以滑鼠右鍵按一下方案總管中每個管線資料夾,然後選擇 [加入至專案],在專案中包含管線和增益集組件。

  2. 從 [屬性] 視窗將每個管線組件和增益集組件的 [建置動作] 設定為 [內容]

最後一個步驟,是設定應用程式資訊清單包含管線組件檔和增益集組件檔以供下載。 這些檔案應該位於 XBAP 應用程式佔用之 ClickOnce 快取根資料夾的資料夾中。 執行下列作業可在 Visual Studio 內完成設定:

  1. 以滑鼠右鍵按一下 XBAP 專案,再依序按一下 [屬性]、[發佈] 和 [應用程式檔案] 按鈕。

  2. 在 [應用程式檔案] 對話方塊中,將每個管線和增益集 DLL 的 [發行狀態] 設成 [Include (Auto)] (包含 (自動)),並將每個管線和增益集 DLL 的 [下載群組] 設成 [(必要項)]

使用來自應用程式基底的管線和增益集

針對 ClickOnce 部署設定管線和增益集時,系統會將這些項目下載到和 XBAP 相同的 ClickOnce 快取資料夾。 若要使用來自 XBAP 的管線和增益集,XBAP 程式碼必須從應用程式基底加以取得。 使用管線和增益集的各種 .NET Framework 增益集模型類型和成員,可為此狀況提供特殊支援。 首先,路徑是由 ApplicationBase 列舉值來識別。 您使用此值與相關增益集成員的多載處理使用包含下列各項的管線︰

存取裝載的原始網站

為確保增益集能參考原始網站的檔案,必須使用相當於主應用程式的安全性隔離載入增益集。 此安全性層級是由 AddInSecurityLevel.Host 列舉值所識別,並在增益集啟動時傳遞至 Activate 方法。

WPF 增益集架構

如我們所見,在最高層級中,WPF 可讓 .NET Framework 增益集使用 INativeHandleContractViewToContractAdapterContractToViewAdapter 實作使用者介面 (直接或間接衍生自 FrameworkElement)。 結果是主應用程式傳回從主應用程式之 UI 顯示的 FrameworkElement

若為簡單的 UI 增益集案例,這是開發人員需要的最詳細資料。 若為更複雜的案例,特別是嘗試使用其他 WPF 服務,例如版面配置、資源及資料繫結,需要更深入瞭解 WPF 如何擴充 .NET Framework 增益集模型與 UI 支援,以瞭解其優點和限制。

基本上,WPF 不會從增益集將 UI 傳送到主應用程式;而是 WPF 使用 WPF 互通性傳送 UI 的 Win32 視窗控制代碼。 因此,當 UI 從增益集傳遞至主應用程式時,會發生下列情況︰

  • 在增益集端,WPF 會取得主應用程式將顯示之 UI 的視窗控制代碼。 視窗控制代碼是由衍生自 HwndSource 的內部 WPF 類別封裝,並會實作 INativeHandleContract。 此類別的執行個體是由 ViewToContractAdapter 傳回,並且從增益集應用程式定義域到主應用程式的應用程式定義域進行封送處理。

  • WPF 會在主應用程式端將 HwndSource 重新封裝為衍生自 HwndHost 的內部 WPF 類別,並取用 INativeHandleContract。 此類別的執行個體會由 ContractToViewAdapter 傳回主應用程式。

HwndHost 的存在目的,是顯示 WPF 使用者介面內視窗控制代碼所識別的使用者介面。 如需詳細資訊,請參閱 WPF 和 Win32 互通

總而言之,INativeHandleContractViewToContractAdapterContractToViewAdapter 存在,即可允許將 WPF UI 的視窗控制代碼從增益集傳遞至主應用程式,HwndHost 會在其中由封裝視窗控制代碼,並顯示主應用程式的 UI。

注意

因為主應用程式會取得 HwndHost,所以主應用程式無法將 ContractToViewAdapter 傳回的物件轉換成增益集實作的類型 (例如,UserControl)。

HwndHost 在本質上有一定的限制,會影響主應用程式加以使用的方式。 不過,WPF 會在不同增益集案例使用數個功能來擴充 HwndHost。 下文說明這些優點與限制。

WPF 增益集的優點

因為 WPF 增益集使用者介面是使用衍生自 HwndHost 的內部類別從主應用程式顯示,所以這些使用者介面受限於與 WPF UI 服務相關的 HwndHost 功能,例如版面配置、轉譯、資料繫結、樣式、範本和資源。 不過,WPF 會擴大其內部 HwndHost 子類別與其他功能,包括:

  • 切換主應用程式的 UI 和增益集的 UI。 請注意,無論增益集是完全受信任或部分受信任,「增益集是 UI」程式設計模型皆需使用增益集端配接器覆寫 QueryContract,以啟用定位處理。

  • 接受從主應用程式使用者介面顯示之增益集使用者介面的協助工具需求。

  • 讓 WPF 應用程式在多個應用程式定義域情況下安全執行。

  • 在增益集使用安全性隔離執行時 (即部分信任安全性沙箱),防止不合法存取增益集 UI 視窗控制代碼。 呼叫 ViewToContractAdapter 可確保此安全性:

    • 針對「增益集傳回 UI」程式設計模型,跨隔離界限傳遞增益集 UI 視窗控制代碼的唯一方法是呼叫 ViewToContractAdapter

    • 針對「增益集是 UI」程序設計模型,必須在增益集端配接器上覆寫 QueryContract 並呼叫 ViewToContractAdapter (如上述範例所示),如同從主機端配接器呼叫增益集端配接器的 QueryContract 實作一樣。

  • 提供多個應用程式定義域執行保護。 由於應用程式定義域的限制,增益集應用程式定義域中擲回的未處理例外狀況會導致整個應用程式當機,即使有隔離界限。 不過,WPF 和 .NET Framework 增益集模型提供簡單的方式來解決這個問題,並改善應用程式穩定性。 如果主應用程式是 WPF 應用程式,顯示 UI 的 WPF 增益集,會為應用程式定義域執行所在的執行緒建立 Dispatcher。 您可以藉由處理 WPF 增益集 DispatcherUnhandledException 事件,偵測應用程式定義域中發生的所有未處理例外狀況。 您可以從 CurrentDispatcher 屬性取得 Dispatcher

WPF 增益集限制

除了 WPF 新增至 HwndSourceHwndHost 和視窗控制代碼所提供預設行為的優點之外,從主應用程式顯示的增益集使用者介面使用者介面也有一些限制:

  • 從主應用程式顯示的增益集使用者介面,不遵守主應用程式的裁剪行為。

  • 互通性案例中的「空間」概念也適用於增益集 (請參閱技術領域概觀)。

  • 主應用程式的 UI 服務 (例如資源繼承、資料繫結和命令) 不會自動提供給增益集使用者介面。 若要向增益集提供這些服務,您需要更新管線。

  • 增益集 UI 不能進行旋轉、縮放、扭曲,也不會受到轉換影響 (請參閱轉換概觀)。

  • 使用 System.Drawing 命名空間繪製作業轉譯之增益集使用者介面內的內容,可以包含 alpha 混色。 不過,包含其的增益集 UI 和主應用程式 UI,兩者都必須是 100% 不透明;換句話說,兩者的 Opacity 屬性都必須設為 1。

  • 如果包含增益集 UI 之主應用程式視窗的 AllowsTransparency 屬性設為 true,則增益集不可見。 即使增益集 UI 是 100% 不透明 (也就是 Opacity 屬性值為 1) 也一樣。

  • 增益集 UI 必須出現在相同最上層視窗中其他 WPF 元素的上方。

  • 增益集 UI 中的任何部分都不能使用 VisualBrush 來轉譯。 增益集反倒可能採用所產生之 UI 的快照集建立點陣圖,其可以傳遞至使用合約所定義方法的主應用程式。

  • 您無法從增益集 UI 中的 MediaElement 播放媒體檔案。

  • 主應用程式不接收也不引發針對增益集 UI 產生的滑鼠事件,而主應用程式 UI 的 IsMouseOver 屬性有值 false

  • 當焦點在增益集 UI 的控制項之間移動時,主應用程式不接收也不引發 GotFocusLostFocus 事件。

  • 包含增益集 UI 的主應用程式在列印時有部分會出現白色。

  • 如果主應用程式繼續執行,必須先手動關閉增益集 UI 建立的所有 Dispatcher (請參閱 Dispatcher),再卸載擁有者增益集。 合約可以實作讓主應用程式先通知增益集再卸載增益集的方法,藉此讓增益集 UI 關閉其 Dispatcher。

  • 如果增益集 UI 是 InkCanvas 或包含 InkCanvas,則您無法卸增益集。

效能最佳化

根據預設,當使用多個應用程式定義域時,每個應用程式需要的各種 .NET Framework 組件都會載入該應用程式定義域。 如此一來,建立新應用程式定義域以及從其中啟動應用程式所需的時間,可能會影響效能。 不過,.NET Framework 會提供方法讓您降低啟動時間,如果已載入,請指示應用程式在各應用程式定義域間共用組件。 您可以使用 LoaderOptimizationAttribute 屬性執行此作業,其必須套用至進入點方法 (Main)。 在此情況下,您必須只使用程式碼實作您的應用程式定義 (請參閱應用程式管理概觀)。

另請參閱