类型说明符概述

更新:2007 年 11 月

TypeDescriptor 结构增强了 .NET 反射的各种功能。

类型说明符结构

TypeDescriptor 结构建立在核心反射引擎的基础上添加了其他一些规则和功能。例如,TypeDescriptor 类支持合并 IContainer 中的扩展程序属性,还支持通过 IDesigner 筛选属性和事件。

另外,TypeDescriptor 结构启用了多种功能。下表列出了该结构的各种功能。

功能

说明

实例替换

在请求一个类型时允许创建另一个任意类型。

元数据替换

允许修改对象的元数据。

属性重定向

允许动态指定属性。

目标替换和影化

允许一个对象代替另一个对象。

扩展的类型说明符支持

允许访问由其他对象添加的对象属性。

为了支持这些功能,TypeDescriptor 类与 .NET Framework 组件模型的各种功能紧密集成到了一起。它与 COM 对象、扩展程序提供程序、设计器和 CLR 属性兼容。

ms171819.alert_note(zh-cn,VS.90).gif说明:

您可以在您的运行时代码及设计时代码中使用 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 类可以解决此问题。在一个属性 (Property) 上设置此属性 (Attribute) 后,为属性 (Property) 说明符的 Attributes 集合获取属性 (Attribute) 的规则将发生更改。通常,属性 (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 类自动合并这两个属性集合的结果。

ms171819.alert_note(zh-cn,VS.90).gif说明:

尽管 .NET Framework 组件模型仅支持扩展的属性 (Property),但如果类型描述提供程序支持,GetExtendedTypeDescriptor 也可用于扩展的属性 (Attribute) 和事件。

请参见

参考

TypeDescriptor

TypeDescriptionProvider

TypeDescriptionProviderAttribute

ICustomTypeDescriptor

CustomTypeDescriptor

IContainer

IDesigner

其他资源

扩展设计时支持