共用方式為


中繼資料存放區

更新:2007 年 11 月

Windows Presentation Foundation (WPF) Designer for Visual Studio 架構將設計階段中繼資料與實作分開處理。將中繼資料與執行階段程式碼分開處理是一項重要的設計原則,原因如下。

  • 小組之間的來回建置和整合工作可能會使中繼資料編譯到架構程式碼變得十分麻煩。

  • 將中繼資料編譯到執行階段程式碼,外部工具 (如 WPF 設計工具或 Expression Blend) 稍後就無法修改這些中繼資料。這會嚴重影響靈活度。若未將設計階段中繼資料與程式碼分開處理,Visual Studio 就需要新版 .NET Framework,才能建立設計工具的版本。

  • 將中繼資料編譯到執行階段會大幅增加執行階段組件的大小。設計階段屬性也會拖慢執行階段的速度。像是資料繫結等使用反映 (Reflection) 的執行階段功能會因其他屬性載入記憶體而受到影響。

  • 設計階段中繼資料能提供設計工具的「特質」。設計工具的功能多半繫結到裝載它的應用程式,而非執行階段。WPF 設計工具和 Expression Blend 使用不同的中繼資料集,針對特定類型的使用者提供功能集。

中繼資料存放區

中繼資料存放區是儲存設計階段中繼資料的位置。中繼資料存放區的 API 很簡單。您可以呼叫 AddAttributeTable 方法,加入中繼資料屬性的表格。當表格加入到中繼資料存放區時,該表格中定義的屬性便可透過 TypeDescriptor 查詢使用。如果已經查詢過某個型別,而表格包含該型別的其他屬性,就會引發 Refreshed 事件,報告該型別的中繼資料已變更。

屬性表格

屬性表格實質上就是唯讀的字典,但是索引鍵和值是分開來計算的。如果要查詢屬性表格中是否有特定型別的屬性,這會比較有效率。實際上,屬性集合都是視需求而建立的。您可以呼叫 GetCustomAttributes 方法,以擷取特定型別的自訂中繼資料。

屬性 (Attribute) 表格只支援型別的屬性 (Property)。屬性 (Attribute) 表格不支援欄位或方法上的屬性 (Attribute)。

屬性表格產生器

若要建立屬性表格,必須從建立 AttributeTableBuilder 類別的執行個體開始。接著再呼叫 AddCustomAttributes 多載,將中繼資料加入至屬性表格產生器。完成加入中繼資料的動作後,您必須呼叫 CreateTable 方法,從屬性表格產生器產生屬性表格。屬性表格方法支援回呼委派,因此可延後建立屬性表格,直到有需求為止。

自訂屬性建立

中繼資料存放區需仰賴自訂屬性 (Attribute) 的 TypeId 屬性 (Property) 有正確定義的覆寫。中繼資料存放區會使用 TypeId 屬性 (Property) 來判斷相同或不同型別的兩個屬性 (Attribute) 是否應視為相同的執行個體。

基底 Attribute 類別會將 TypeId 屬性 (Property) 定義如下。

    public class Attribute
    {
        ...

        public virtual object TypeId
        {
            get
            {
                return base.GetType();
            }
        }

        ...
    }

此實作會讓相同 Attribute 型別的兩個執行個體顯示成相同的屬性 (Attribute)。預設 TypeDescriptor 實作會忽略其中一個執行個體。如果不要自訂屬性 (Attribute) 的這項行為 (如同 FeatureAttribute 類別的情況),自訂屬性 (Attribute) 就必須覆寫 TypeId 屬性 (Property),針對每個型別執行個體傳回唯一的物件。例如,FeatureAttribute 類別可使用下列程式碼覆寫 TypeId 屬性 (Property)。

public override object TypeId
{
    get { return this; }
}

由於 this 表示每個物件執行個體的唯一物件,因此 FeatureAttribute 可以安全地裝飾相同的類別多次,並能在與中繼資料存放區搭配使用時產生所要的結果。

中繼資料組件的命名規範

設計階段程式碼部署在特殊中繼資料組件中。所有設計工具支援的設計階段功能都會部署在名稱為主程式庫名稱再加上 ".Design" 的組件中。只有 Visual Studio 支援的設計階段功能則會部署在名稱為主程式庫名稱再加上 ".VisualStudio.Design" 的組件中。下表顯示名為 CustomControlLibrary.dll 的執行階段控制項程式庫的範例名稱。

設計工具

設計階段組件名稱

僅限 Visual Studio

CustomControlLibrary.VisualStudio.Design.dll

僅限 Expression Blend

CustomControlLibrary.Expression.Design.dll

所有設計工具

CustomControlLibrary.Design.dll

載入中繼資料組件

當設計工具載入執行階段組件時,設計工具也會搜尋相對應的中繼資料組件。如果找到相對應的中繼資料組件,這些組件就會在執行階段組件載入之後立即載入。

當您將新的組件參考加入到專案中,會搜尋所有相對應的中繼資料組件,並在找到之後載入。

中繼資料組件在重建之後會重新載入。

注意事項:

*.Design.dll 中繼資料組件會先載入,然後再載入設計工具特定的 *.VisualStudio.Design.dll 和 *.Expression.Design.dll 組件。設計工具特定的中繼資料會覆寫共用中繼資料。

中繼資料組件搜尋順序

下列搜尋順序適用於專案直接參考的組件。

  1. 設計工具搜尋與參考的執行階段組件相同的資料夾。此位置會使用組建 (Build) 用來尋找組件的相同演算法來搜尋,這包括搜尋 SDK 資料夾和其他路徑。

  2. 設計工具搜尋控制項的執行階段組件所在資料夾的 "Design" 子資料夾。

雖然控制項的執行階段組可從件全域組件快取 (GAC) 載入,但參考的都一定是 GAC 以外的位置。此位置通常會於 SDK 資料夾中。WPF 設計工具會使用 Visual Studio API 搜尋檔案系統上的參考組件,即使沒有指定專案的 HintPath。設計工具會嘗試從參考控制項的執行階段組件的位置載入中繼資料組件,而不是從載入控制項的執行階段組件的位置。

間接參考的組件會載入,因為專案參考的組件參考它們。例如,如果您的專案具有組件 MyAssembly 的參考,而 MyAssembly 則具有 MyOtherAssembly 的參考,但專案並未直接參考後者,則 MyOtherAssembly 就是間接參考的組件。

在這種情況下,建置 (Build) 時不需要該組件,而且建置系統也不會在檔案系統中尋找間接參考組件的位置。下表顯示設計工具如何載入間接參考的組件。

參考的組件

搜尋程序

從 GAC 載入的檔案

搜尋 SDK 資料夾是否有相對應的中繼資料組件。如果找到此組件,就會使用其路徑和其下的 "Design" 子資料夾來搜尋任何相對應的中繼資料組件。

從 GAC 以外的位置載入的檔案

搜尋執行階段組件的路徑和其下的 "Design" 子資料夾是否有相對應的中繼資料組件。

尋找 IRegisterMetadata 實作

中繼資料組件必須包含 IRegisterMetadata 介面的一個或多個實作。IRegisterMetadata 實作會使用反映來尋找。如果有多個 IRegisterMetadata 實作存在於組件中,每一個都會以反映 API 傳回的順序執行個體化和呼叫。

請參閱

參考

Microsoft.Windows.Design.Metadata

MetadataStore

AttributeTable

AttributeTableBuilder

FeatureAttribute

其他資源

WPF 設計工具擴充性