支持类型转换器和标记扩展用法的类型的作者通常必须拥有标记或周围对象图结构中存在此用法的位置的相关上下文信息。 为了能正确实例化所提供的对象或者对对象图中的现有对象进行对象引用,可能需要此信息。 使用 .NET Framework XAML 服务时,可能需要的上下文将作为一系列服务接口公开。 类型转换器或标记扩展支持代码可使用从 XamlObjectWriter 或相关类型传递且可用的服务提供程序上下文来查询服务。 可通过一个这样的服务来直接获取 XAML 架构上下文。 本主题介绍如何从值转换器实现访问服务上下文,并且列出了通常可用的服务及其作用。
本主题包括下列各节。
- 获取服务
- 用于标记扩展的服务
- 用于类型转换器的服务
- 用于值序列化程序的服务
- 使用 XAML 服务提供程序上下文
- .NET Framework XAML 服务上下文中可用的服务
- 相关主题
获取服务
作为值转换器的实施者,您经常需要访问在其中应用了值转换器的某些类型上下文。 此上下文可能包括诸如活动的 XAML 架构上下文的信息、访问 XAML 架构上下文和 XAML 对象编写器提供的类型映射系统等。 可用于标记扩展或类型转换器实现的服务将通过属于每个虚方法签名的上下文参数来传递。 对于上述每种情况,您都在上下文中实现了 IServiceProvider 并且可以调用 IServiceProvider.GetService 来请求服务。
用于标记扩展的服务
MarkupExtension 只有一个虚方法 ProvideValue。 输入 serviceProvider 参数就是在 XAML 处理器调用标记扩展时服务与实现的通信方式。 以下伪代码演示了标记扩展实现如何在其 ProvideValue 中查询服务:
public override object ProvideValue(IServiceProvider serviceProvider)
{
...
// Get the IXamlTypeResolver from the service provider
if (serviceProvider == null)
{
throw new ArgumentNullException("serviceProvider");
}
IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
if (xamlTypeResolver == null)
{
throw new ArgumentException("IXamlTypeResolver"));
}
...
}
用于类型转换器的服务
TypeConverter 具有四个虚方法,这些方法都使用一个服务上下文并且都支持 XAML 用法。 每个方法都传递一个输入 context 参数。 此参数的类型为 ITypeDescriptorContext,但该接口会继承 IServiceProvider,因此具有一个可用于类型转换器实现的 GetService 方法。
以下伪代码演示了在本例 ConvertFrom 中 XAML 用法的类型转换器实现如何在它的一个重写中查询服务:
public override object ConvertFrom(ITypeDescriptorContext typeDescriptorContext,
CultureInfo cultureInfo,
object source)
{
IRootObjectProvider rootProvider = typeDescriptorContext.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
if (rootProvider != null && source is String)
{
//return something, else ...
}
throw GetConvertFromException(source);
}
用于值序列化程序的服务
对于值序列化程序上下文,可使用特定于 ValueSerializer 类 IValueSerializerContext 的服务提供程序类型。 该上下文传递给四个 ValueSerializer 虚方法的重写方法。 从上下文中调用 GetService 以获取服务。
使用 XAML 服务提供程序上下文
对标记扩展或类型转换器可使用的 XAML 服务的 GetService 访问所用的服务提供程序作为内部类实现,并且仅通过接口以及将其传递到相关上下文的方式公开。 只要加载路径或保存路径的默认 .NET Framework XAML 服务实现中的 XAML 处理操作调用需要服务上下文的相关标记扩展或类型转换器方法,就会传递此内部对象。 根据具体情况,系统服务上下文提供 MarkupExtensionContext 或 TextSyntaxContext,但这两个特定类都是内部类。 您与这些类的交互仅限于通过 GetService 从中请求服务。
.NET Framework XAML 服务上下文中可用的服务
.NET Framework XAML 服务为标记扩展、类型转换器、值序列化程序以及可能的其他用法定义服务。 以下各节介绍每种服务,并提供有关在实现中如何使用服务的指导。
IServiceProvider
参考文档:IServiceProvider
相关内容:.NET Framework 中基于服务的基础结构的基本操作,以便您可以调用 IServiceProvider.GetService。
ITypeDescriptorContext
派生自 IServiceProvider。 此类表示标准 TypeConverter 签名中的上下文;TypeConverter 是一个自 .NET Framework 1.0 版以来就已存在的类。该类早于用于字符串到值类型转换的 XAML 和 XAML TypeConverter 方案。 在 .NET Framework XAML 服务上下文中,TypeConverter 的方法是显式实现的。 此显式实现的行为向调用方指示 ITypeDescriptorContext API 与 XAML 类型系统无关,或者与 XAML 中的读取或写入对象无关。 Container、Instance 和 PropertyDescriptor 通常会从 .NET Framework XAML 服务上下文返回 null。
IValueSerializerContext
派生自 ITypeDescriptorContext 并且还依赖于显式实现以抑制有关 XAML 类型系统的错误含义。 支持 ValueSerializer 上的静态查找帮助器方法。
IXamlTypeResolver
参考文档:IXamlTypeResolver
由以下内容定义:System.Windows.Markup 命名空间、System.Xaml 程序集
**相关内容:**加载路径方案以及与 XAML 架构上下文的交互
服务 API:Resolve
可能会影响 XAML 到 CLR 类型映射,当 XAML 编写器在对象图中构造 CLR 对象时,此映射是必要的。 Resolve 处理一个与 XAML 类型名称 (XamlType.Name) 对应的可能由前缀限定的字符串并返回一个 CLR Type。 解析类型通常很大程度上取决于 XAML 架构上下文。 只有 XAML 架构上下文了解注意事项,如加载哪些程序集以及可以或应访问其中哪些程序集以进行类型解析。
IUriContext
参考文档:IUriContext
由以下内容定义:System.Windows.Markup 命名空间、System.Xaml 程序集
**相关内容:**是 URI 或 x:Uri 值的成员值的加载路径和保存路径处理。
服务 API:BaseUri
此服务报告一个全局可用的 URI 根(如果有的话)。 可以使用此 URI 根将相对 URI 解析为绝对 URI,反之亦然。 此方案主要与由特定框架或框架中常用根元素类的功能公开的应用程序服务有关。 可以采用 XAML 读取器设置的方式建立基 URI,然后传递给 XAML 对象编写器并由此服务进行报告。
IAmbientProvider
参考文档:IAmbientProvider
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**加载路径处理以及类型查找推迟或优化。
服务 API:GetAllAmbientValues、三个其他 API。
XAML 中的环境概念是一种将类型的特定成员标记为环境的方法。 或者,某种类型也可以是环境,以便包含该类型实例的所有属性值都应视为环境属性。 沿 XAML 节点流前进或作为对象图中的后代的标记扩展或类型转换器可以在加载时访问环境属性或类型实例;也可以在保存时使用环境结构的知识。 这可能会影响其他服务(例如,IXamlTypeResolver 或 x:Type)的类型解析所需的限定程度。 另请参见AmbientPropertyValue。
IXamlSchemaContextProvider
参考文档:IXamlSchemaContextProvider
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**加载路径以及必须将 XAML 类型解析为后备类型的任何操作。
服务 API:SchemaContext
对于任何推迟加载操作来说,XAML 架构上下文都是必需的,因为同一架构上下文必须作用于推迟的区域才能集成推迟的内容。 有关 XAML 架构上下文的作用的更多信息,请参见 XAML 服务。
IRootObjectProvider
参考文档:IRootObjectProvider
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**加载路径。
服务 API:RootObject
该服务与由特定框架或框架中常用根元素类的功能公开的应用程序服务有关。 一种获取根对象的情况是连接代码隐藏和事件连结。 例如,x:Class 的 WPF 实现用于 XAML 标记中任何其他位置处的任何事件处理程序特性的标记编译和连结。 标记与为标记编译定义分部类的代码隐藏的连接点在根元素处。
IXamlNamespaceResolver
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**加载路径,保存路径。
服务 API: GetNamespace 用于加载路径、GetNamespacePrefixes 用于保存路径。
IXamlNamespaceResolver 是一个服务,该服务可按照原始 XAML 标记中映射的方式基于 XAML 命名空间的前缀返回 XAML 命名空间标识符/URI。
IProvideValueTarget
参考文档:IProvideValueTarget
由以下内容定义:System.Windows.Markup 命名空间、System.Xaml 程序集
**相关内容:**加载路和保存路径。
服务 API:TargetObject、TargetProperty。
IProvideValueTarget 可使类型转换器或标记扩展能够获取有关加载时作用位置的上下文。 实现可能使用此上下文来使某个用法失效。 例如,WPF 在其某些标记扩展(例如 DynamicResourceExtension)中具有逻辑。 该逻辑检查 TargetProperty 以确保该扩展仅用于设置依赖项属性(或其他非依赖项属性的简短列表)。
IXamlNameResolver
参考文档:IXamlNameResolver
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**加载路径对象图定义,解析由 x:Name、x:Reference 或特定于框架的技术标识的对象。
服务 API:Resolve;用于更高级方案(例如,处理前向引用)的其他 API。
x:Reference 处理的 .NET Framework XAML 服务实现依赖于此服务。 特定框架或支持框架的工具使用此服务进行 x:Name 处理或等效的(RuntimeNamePropertyAttribute 特性化的)属性处理。
IDestinationTypeProvider
由以下内容定义:System.Xaml 命名空间、System.Xaml 程序集
**相关内容:**间接 CLR 类型信息的加载路径解析。
服务 API: GetDestinationType
有关更多信息,请参见 IDestinationTypeProvider。