型別描述項概觀

TypeDescriptor 架構加強了 .NET 反映 (Reflection) 的功能。

型別描述項架構

TypeDescriptor 架構是建置在核心反映引擎上,並加入其他規則和功能。 例如,TypeDescriptor 類別從 IContainer 支援合併擴充性屬性,同時也透過 IDesigner 支援篩選屬性和事件。

此外,TypeDescriptor 架構也啟用了一些功能。 下表列出架構的功能。

功能

說明

執行個體替換

在要求另一個型別時,能夠建立任意型別

中繼資料替換

使物件的中繼資料能夠進行修改

屬性重新導向

使屬性能夠以動態方式指定

目標替換和遮蔽

使一個物件能夠代替另一個物件

擴充型別描述項支援

能夠存取由其他物件加入的物件屬性

若要支援這些功能,TypeDescriptor 類別必須與 .NET Framework 元件模型的各種不同功能密切整合。 它與 COM 物件、擴充性提供者、設計工具和 CLR 屬性都相容。

注意事項注意事項

您可以在執行階段程式碼和設計階段程式碼中,使用 TypeDescriptor 架構。

若要支援擴充性,TypeDescriptor 類別具有名為 TypeDescriptionProvider 的伴隨類別,和名為 TypeDescriptionProviderAttribute 的伴隨屬性。 您可以使用類別上的 TypeDescriptionProviderAttribute,引入完全不同的方式,公開符合設計目標的中繼資料。

TypeDescriptionProvider 類別

TypeDescriptionProvider 類別可以視為 TypeDescriptor 類別的外掛程式。 對於 TypeDescriptor 的特定執行個體,可以有多個型別描述提供者類別,全部都會提供中繼資料給 TypeDescriptor

TypeDescriptionProvider 屬性

TypeDescriptionProviderAttribute 是您可以放在類別上的屬性。 這個屬性是用來表示型別具有與其相關聯的自訂型別描述提供者。 然後屬性會提供方法,透過中繼資料,安裝型別描述提供者。 當型別傳遞給 TypeDescriptor 類別上的任何 API 時,TypeDescriptor 會探索這個屬性、建立其中所描述型別描述提供者的執行個體,並讓提供者連結 TypeDescriptor 的內部資料表。 完成這項作業以後,TypeDescriptor 會繼續處理 API。 這項處理允許型別應要求自動安裝自訂型別描述提供者。

型別描述項功能

TypeDescriptor 架構啟用了 .NET Framework 反映所提供以外的功能。

執行個體替換

在您要建立一個型別,但所建立的型別與所要求型別不同時,就會發生執行個體替換。 執行個體替換是在您以 CreateInstance 方法呼叫取代所有 new 呼叫時完成。 這個方法會搜尋 TypeDescriptor 之中的內部資料表,找尋與指定資料型別相關聯的 TypeDescriptionProvider 物件。 如果找到一個物件,就會委派呼叫給該物件。

中繼資料替換

要修改一個或多個物件可用的中繼資料時,就會發生中繼資料替換。 一個常見的中繼資料替換應用程式就是設計工具的實作。 中繼資料替換可以利用型別描述提供者完成,提供者可以使用下列方法在 TypeDescriptor 上加入或移除:

屬性重新導向

.NET Framework 物件模型中會有少數幾種情況,刻意將屬性的型別做為非特定型別。 例如,DataGridView 類別上的 DataSource 屬性是輸入為 object。 這項設計允許資料來源接受幾種輸入,但不提供加入中繼資料的一般位置,以描述屬性的特性。 整個 .NET Framework 的每一個資料來源屬性都必須有完全相同的中繼資料,供型別轉換子和使用者介面 (UI) 型別編輯器使用。

AttributeProviderAttribute 類別可以處理這種情況。 將屬性 (Attribute) 放在屬性 (Property) 上時,取得屬性 (Property) 描述項之 Attributes 集合的規則就會變更。 通常屬性 (Property) 描述項會收集目標屬性 (Attribute),並與屬性 (Property) 型別的屬性 (Attribute) 合併。 套用 AttributeProviderAttribute 屬性 (Attribute) 時,屬性 (Attribute) 是從 AttributeProviderAttribute 傳回的型別中取得,而不是從實際屬性 (Property) 中取得。 AttributeProviderAttribute 是用在資料來源上,將資料來源的特定型別指向 IListSource,而且適當的中繼資料是放在 IListSource 上,以啟用資料繫結。 這種重新導向可以讓外部作業單位,例如 Visual Studio,很容易就能將中繼資料加入至所有資料來源中。

AttributeProviderAttribute 中宣告的型別取得的屬性 (Attribute) 具有屬性 (Property) 的型別之屬性 (Attribute) 與屬性 (Property) 上之屬性 (Attribute) 之間的優先權。 可用的一組完整的屬性 (Attribute) 是依優先權順序合併,如下列清單所示:

  1. 屬性屬性 (Property Attribute)

  2. 屬性 (Attribute) 提供者屬性 (Attribute)

  3. 屬性 (Property) 型別屬性 (Attribute)

目標替換和遮蔽

一個物件代替另一個物件時,就會發生目標替換。 一個常見的目標替換應用程式就在設計工具的實作之中。

在 .NET Framework 設計工具架構中,元件可以有設計工具與其產生關聯。 這個設計工具可以實作 IDesignerFilter,並自行提供其屬性。 這些屬性是合併於與設計工具相關聯的元件之屬性集中。 這些屬性可以是元件的新屬性。 它們也可以與元件上已經定義的屬性具有相同的名稱和型別。 當新的屬性與現有屬性共用名稱和型別時,稱為「遮蔽」,因為設計工具會隱藏 (或遮蔽) 元件上現有的屬性。 下列說明會顯示出屬性的遮蔽。

遮蔽文字屬性

元件在此處提供兩個屬性,而設計工具也提供兩個屬性。 Text 屬性是同時提供給設計工具和元件,而且正在進行遮蔽。 呼叫 GetProperties 的最後結果是三個屬性。 一個在元件上,另外兩個在設計工具上。

這種屬性篩選是透過使用由設計介面實作的 ITypeDescriptorFilterService 來完成。 到了在屬性上設定值的時候,就必須要有TypeDescriptor 功能。 在 Grid 屬性上設定值的程式碼如下所示:

    gridProp.SetValue(component, value);

有關屬性的實際型別資訊會將它指向設計工具的執行個體,而不是指向元件。 如果執行反映呼叫,實際設定屬性,呼叫會引發目標引動例外狀況,因為元件執行個體與設計工具型別不相符。

TypeDescriptor 類別具有解決這種狀況的繼承邏輯。 呼叫屬性時,TypeDescriptor 類別會進行檢查,查看成員型別是否為所傳遞物件的執行個體。 如果是,它會讓呼叫繼續進行。 如果不是,此類別會找出物件的設計工具,而且如果可以找到設計工具,是正確的型別,類別是以設計工具執行個體取代元件執行個體。

TypeDescriptor 上的下列方法會支援目標替換:

擴充型別描述項支援

GetExtendedTypeDescriptor 方法會傳回指定物件的擴充自訂型別描述項。 擴充型別描述項是自訂型別描述項,提供其他物件已加入至此物件,但不是在物件上實際定義的屬性。 例如,在 .NET Framework 元件型模中,實作 IExtenderProvider 介面的物件可以附加屬性至存放在相同 IContainer 中的其他物件。 GetTypeDescriptor 方法不會傳回提供這些額外擴充屬性的型別描述項,但 GetExtendedTypeDescriptor 會傳回這些擴充的屬性集。 TypeDescriptor 類別會自動合併這兩個屬性集合的結果。

注意事項注意事項

雖然 .NET Framework 元件模型只支援擴充的屬性 (Property),但如果型別描述提供者有支援,GetExtendedTypeDescriptor 也可以用來擴充屬性 (Attribute) 和事件。

請參閱

參考

TypeDescriptor

TypeDescriptionProvider

TypeDescriptionProviderAttribute

ICustomTypeDescriptor

CustomTypeDescriptor

IContainer

IDesigner

其他資源

擴充設計階段支援