迁移到 v3.0.0

v2.20.0 和 v3.0.0 之间的许多中断性变更可能需要更改源级别。 提醒一下,有两种类型的中断性变更:

  1. 二进制:当二进制文件不能再用作替代项时
  2. :当源不再编译时

在 v3.0.0 中所做的更改要么是删除 SDK 中存在的一段时间的过时,要么是出于体系结构原因而需要进行的更改, (最明显的是,为了获得更好的 AOT 支持和剪裁) 。 这些更改中的大多数应位于 二进制 中断性变更端,同时仍支持使用以前的代码进行编译和预期行为。 但是,需要注意一些源中断性事件。

中断性变更

.NET Standard 1.3 支持已删除

没有任何目标仍支持 .NET Standard 1.3,并且可以改用 .NET Standard 2.0。 该项目仍支持 .NET Framework 3.5+ 和任何 .NET Standard 2.0 支持的平台

所需操作:如果使用 .NET Standard 1.3,请升级到受支持的 .NET 版本

目标框架已更改

为了简化包创建,已针对某些包更改了生成的 TPM。 但是,用户不应有明显的变化,因为除了上面所述的 .NET Standard 1.3 之外, (整体支持的平台) 保持不变。

所需操作:无

OpenXmlPart/OpenXmlContainer/OpenXmlPackage 不再具有公共构造函数

这些从未初始化过正确的行为,也不应该公开。

所需操作:使用 .Create(...) 方法而不是构造函数。

OpenXML 类型的支持框架现在位于 DocumentFormat.OpenXml.Framework 包中

从 v3.0.0 开始,Open XML SDK 的支持框架现在位于独立包 DocumentFormat.OpenXml.Framework 中

需要执行的操作:如果只想对 OpenXmlPackage 类型进行操作,则不再需要引入所有静态类,只需引用框架库。

不再直接使用 System.IO.Packaging

从 System.IO.Packaging 命名空间获取行为存在问题。 从 v3.0 开始,命名空间中的 DocumentFormat.OpenXml.Packaging 一组新接口将用于访问包属性。

注意

这些类型当前标记为已过时,但仅从某种意义上说,我们保留根据反馈更改其形状的权利。 请谨慎使用这些类型,因为它们将来可能会更改。 在某些时候,我们将删除过时,它们将被视为稳定的 API。 有关详细信息,请参阅 此处

所需操作:如果使用 OpenXmlPackage.Package,则返回的包类型不再为 System.IO.Packaging.Package,而是 DocumentFormat.OpenXml.Packaging.IPackage

部件上用于添加子部件的方法现在是扩展方法

有许多重复的方法会以明确定义的方式添加部分。 为了合并这一点,如果部件支持 ISupportedRelationship<T>,则可以编写扩展方法以支持部件可以提供的特定行为。 编译时,应以透明方式将现有方法重新定向到新的扩展方法。

所需操作:无

OpenXmlAttribute 现在是只读结构

此类型用于具有可变 getter 和 setter。 作为一个结构,它很容易被滥用,应该从一开始就单独进行读取。

所需操作:如果希望就地改变 OpenXmlAttribute,请改为创建一个新版本。

EnumValue<TEnum> 现在包含结构

从 v3.0.0 开始, EnumValue<T> 包装包含枚举值相关信息的自定义类型。 以前,这些类型存储在 C# 类型系统中的枚举值中,但需要反射才能访问,从而导致非常大的 AOT 编译应用程序。

需要执行的操作:类似的 API 图面可用,但公开的枚举值不再是常量,在已 (的少数情况下不可用,例如属性值) 。

一个常见的更改是 switch 语句不再有效:

switch (theCell.DataType.Value)
{
  case CellValues.SharedString:
    // Handle the case
    break;
}

成为:

if (theCell.DataType.Value == CellValues.SharedString)
{
  // Handle the case
}

OpenXmlElementList 现在是一个结构

OpenXmlElementList 现在是一个结构。 除了在可用的情况下,IReadOnlyList<OpenXmlElement>它仍然实现IEnumerable<OpenXmlElement>

需要执行的操作:因为这是一个结构,因此可能具有 null 结果的代码模式现在将 OpenXmlElementList? 改为 。 空检查将由编译器标记,并且需要取消包装值本身,例如:

- OpenXmlElementList? slideIds = part?.Presentation?.SlideIdList?.ChildElements;
+ OpenXmlElementList slideIds = part?.Presentation?.SlideIdList?.ChildElements ?? default;

- OpenXmlElementList? slideIds = part?.Presentation?.SlideIdList?.ChildElements;
+ OpenXmlElementList slideIds = (part?.Presentation?.SlideIdList?.ChildElements).GetValueOrDefault();

IdPartPair 现在是只读结构

此类型用于枚举部件中的对,并导致许多不必要的分配。 重新编译时,此更改应是透明的。

需要执行的操作:由于这是一个结构,因此需要更新 null 处理代码。

OpenXmlPartReader 不再知道所有部件

在以前的版本中, OpenXmlPartReader 了解所有强类型部件。 为了减少更好的 AOT 方案所需的耦合,我们现在为已知包键入了读取器: WordprocessingDocumentPartReaderSpreadsheetDocumentPartReaderPresentationDocumentPartReader

所需操作:根据需要,将 的 OpenXmlPartReader 用法替换为文档特定的读取器。 如果从已知包创建部件读取器,请使用采用现有 OpenXmlPart 构造函数,该构造函数将创建预期的强类型部件。

已删除架构信息的属性

SchemaAttrAttributeChildElementInfoAttribute 已从类型中删除,并且类型本身不再存在。

需要执行的操作:如果需要这些类型,请在 GitHub 上与我们联系,以确定最佳前进方式。

已删除 OpenXmlPackage.Close

除了调用 .Dispose()之外,这没有任何用处,但造成了关于应调用哪个调用的混淆。 现在,它已被删除,预期是调用 .Dispose(),最好是 使用 模式

所需操作:删除调用并确保正确释放包

OpenXmlPackage.CanSave 现在是实例属性

此属性过去是依赖于框架的静态属性。 现在,它可能会根据设置和后备存储更改每个包实例。

所需操作:将静态属性的用法替换为实例。

OpenXmlPackage.PartExtensionProvider 已更改

此属性提供了一个字典,允许访问以更改使用的扩展。 现在,这由 提供支持 IPartExtensionFeature

所需操作:将使用情况替换为 OpenXmlPackage.Features.GetRequired<IPartExtensionFeature>()

带有 MarkupCompatibilityProcessMode.ProcessAllParts 的包现在实际处理所有部件

以前,在未加载部件时,有一种启发式方法可以最大程度地减少处理。 但是,这会导致诸如有人手动编辑 XML 以在保存时未实际处理的情况。 v3.0.0 修复了此行为,并处理所有部分(如果已选择这样做)。

所需操作:如果只希望处理已加载的部件,请将 更改为 MarkupCompatibilityProcessMode.ProcessLoadedPartsOnly