默认 XAML 架构上下文和 WPF XAML 架构上下文
XAML 架构上下文是一个概念实体,它限定使用特定 XAML 词汇的 XAML 生产如何与对象写入行为交互,包括类型映射如何解析、如何加载程序集、如何解释某些读取器和编写器设置。 本主题介绍 .NET XAML 服务和关联的默认 XAML 架构上下文的功能,该上下文基于 CLR 类型系统。 本主题还介绍了用于 WPF 的 XAML 架构上下文。
默认 XAML 架构上下文
.NET XAML 服务实现和使用默认 XAML 架构上下文。 默认 XAML 架构上下文行为并不总是在 XamlSchemaContext 类的 API 中完全可见。 但是,在许多情况下,默认 XAML 架构上下文影响的行为可以通过 XAML 类型系统的常见 API(例如 XamlMember 或 XamlType的成员)或通过 XAML 读取器和使用默认 XAML 架构上下文的 XAML 编写器公开的 API 来观察。
可以通过调用 XamlSchemaContext 构造函数来创建封装默认行为的 XamlSchemaContext。 这会显式创建默认 XAML 架构上下文。 如果使用未显式采用 XamlSchemaContext 输入参数的 API 初始化 XAML 读取器或 XAML 编写器,则会隐式创建相同的默认 XAML 架构上下文。
默认 XAML 架构上下文依赖于 CLR 反射来实现其类型映射行为。 这包括检查定义 CLR Type以及相关的 PropertyInfo 或 MethodInfo。 此外,将使用类型或成员的 CLR 属性来填写使用 CLR 支持类型的 XAML 类型或 XAML 成员信息的具体信息。 默认 XAML 架构上下文不需要类型系统扩展技术(如 Invoker
模式),因为 CLR 类型系统提供了必要的信息。
对于程序集加载逻辑,默认 XAML 架构上下文主要依赖于 XAML 命名空间映射中提供的任何程序集值。 此外,对于加载内部类型等方案,LocalAssembly 可以提示要加载的程序集。
WPF XAML 架构上下文
本主题介绍了 WPF XAML 架构上下文,因为 WPF 实现提供了一个有趣的插图,说明可通过实现非默认 XAML 架构上下文来引入的功能类型。 此外,XAML 架构上下文概念在处理 WPF XAML 的 WPF 文档中并未讨论太多;仅当与讨论默认 XAML 架构上下文的工作原理集成时,XAML 架构上下文启用的行为才能完全理解。 WPF XAML 架构上下文实现以下行为。
查找替代: WPF 为 XAML 提供了一些内容模型,其中 XAML 内容属性可在不 ContentPropertyAttribute 特性化的情况下运行。 LookupContentProperty WPF 的替代实现此行为。
WPF 表达式的延迟: WPF 具有多个表达式类,这些表达式类延迟值,直到运行时上下文可用。 此外,模板扩展是依赖于延迟技术的运行时行为。
类型系统查找优化: WPF 具有广泛的 XAML 词汇和对象模型,包括继承到数百个 WPF 定义的类的基类成员定义。 此外,WPF 本身分布在多个程序集中。 WPF 使用查阅表格和其他技术优化其类型查找。 这为默认 XAML 架构上下文及其基于 CLR 的类型查找提供了性能改进。 如果查阅表格中不存在类型,则行为使用类似于默认 XAML 架构上下文的 XAML 架构上下文技术。
XamlType 和 XamlMember 扩展: WPF 使用依赖属性扩展属性概念,以及路由事件的事件概念。 为了提高 XAML 处理操作的可见性,WPF 扩展 XamlType 和 XamlMember,并添加报告依赖属性和路由事件特征的内部属性。
访问 WPF XAML 架构上下文
如果使用基于 WPF System.Windows.Markup.XamlReader 或 System.Windows.Markup.XamlWriter的 XAML 技术,则 WPF XAML 架构上下文已在这些 XAML 读取器和 XAML 编写器实现上使用。
如果使用未使用 WPF XAML 架构上下文初始化的其他 XAML 读取器或 XAML 编写器实现,则可以从 XamlReader.GetWpfSchemaContext获取工作 WPF XAML 架构上下文。 然后,可以将此值用作使用 XamlSchemaContext的其他 API 的初始化。 例如,可以调用 XamlXmlReader 进行初始化并传递 WPF XAML 架构上下文。 或者,可以将 WPF XAML 架构上下文用于 XAML 类型系统操作。 这可能包括 XamlType 或 XamlMember的构造初始化,或调用 XamlSchemaContext.GetXamlType。
请注意,如果从纯 XAML 节点流的角度访问 WPF XAML 的某些方面,则某些 WPF 框架功能可能尚未执行。 例如,尚未应用控件的 WPF 模板。 因此,如果访问运行时可能填充了完整可视化树的属性,则只能看到引用模板的属性值。 如果从非运行时情况提供,则为 WPF 标记扩展提供的服务上下文也可能不准确,并且可能会在尝试写入对象图时导致异常。
XAML 和程序集加载
XAML 和 .NET XAML 服务的程序集加载与 CLR 定义的 AppDomain概念集成。 XAML 架构上下文根据 AppDomain 和其他因素来解释如何在运行时或设计时加载程序集或查找类型。 逻辑略有不同,具体取决于 XAML 是 XAML 读取器的松散 XAML,是 XAML 通过 XamlBuildTask
编译为 DLL,还是由 WPF 的 PresentationBuildTask
生成的 BAML。
WPF 的 XAML 架构上下文与 WPF 应用程序模型集成,后者又使用 AppDomain 以及 WPF 实现详细信息的其他因素。
XAML 读取器输入(松散 XAML)
XAML 架构上下文循环访问应用程序的 AppDomain,查找与名称的所有方面匹配的已加载程序集,从最近加载的程序集开始。 如果找到匹配项,该程序集将用于解析。
否则,以下基于 CLR Assembly API 的技术之一用于加载程序集:
如果名称在映射中限定,请对限定名称调用 Assembly.Load(String)。
如果上一步失败,请使用短名称(如果存在)调用 Assembly.Load(String)。
如果映射中名称不限定,则调用 Assembly.LoadWithPartialName。
XamlBuildTask
XamlBuildTask
用于 Windows Communication Foundation(WCF)和 Windows Workflow Foundation。
请注意,通过 XamlBuildTask
的程序集引用始终完全限定。
对限定名称调用 Assembly.Load(String)。
如果上一步失败,请使用短名称(如果存在)调用 Assembly.Load(String)。
BAML (PresentationBuildTask)
BAML 的程序集加载有两个方面:加载包含 BAML 作为组件的初始程序集,并为 BAML 生产引用的任何类型加载类型支持程序集。
初始标记的程序集加载:
对从中加载标记的程序集的引用始终不限定。
WPF XAML 架构上下文循环访问 WPF 应用程序的 AppDomain,查找与名称的所有方面匹配的已加载程序集,从最近加载的程序集开始。 如果找到匹配项,该程序集将用于解析。
如果上一步失败,请使用短名称(如果存在)调用 Assembly.Load(String)。
BAML 类型的程序集引用:
BAML 生产中使用的类型的程序集引用始终是完全限定的,作为生成任务的输出。
WPF XAML 架构上下文循环访问 WPF 应用程序的 AppDomain,查找与名称的所有方面匹配的已加载程序集,从最近加载的程序集开始。 如果找到匹配项,该程序集将用于解析。
否则,以下技术之一用于加载程序集:
对限定名称调用 Assembly.Load(String)。
如果短名称 + 公钥令牌组合与从中加载 BAML 的程序集匹配,请使用该程序集。
使用短名称 + 公钥令牌调用 Assembly.Load(String)。