Skip to content

Commit

Permalink
Expose IPackageBuilder (#1553)
Browse files Browse the repository at this point in the history
  • Loading branch information
twsouthwick authored Nov 6, 2023
1 parent ad6f12f commit 3976cf1
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 31 deletions.
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
</When>
<When Condition=" '$(ProjectLoadStyle)' == 'All' ">
<PropertyGroup>
<ProductTargetFrameworks>netstandard2.0;net35;net40</ProductTargetFrameworks>
<FrameworkTargetFrameworks>netstandard2.0;net6.0;net35;net40;net46</FrameworkTargetFrameworks>
<ProductTargetFrameworks>netstandard2.0;net35;net40;net7.0</ProductTargetFrameworks>
<FrameworkTargetFrameworks>netstandard2.0;net6.0;net7.0;net35;net40;net46</FrameworkTargetFrameworks>
<AssetsTargetFrameworks>net452;netstandard2.0</AssetsTargetFrameworks>
<TestTargetFrameworks>net452;net462;net6.0;net7.0</TestTargetFrameworks>
<LatestTargetFramework>net7.0</LatestTargetFramework>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@

namespace DocumentFormat.OpenXml.Builder;

internal delegate void PackageInitializerDelegate<TPackage>(TPackage package);

internal interface IPackageBuilder<TPackage>
/// <summary>
/// A delegate for initializing a package.
/// </summary>
public delegate void PackageInitializerDelegate<TPackage>(TPackage package);

/// <summary>
/// Defines a builder to create an initialization pipeline for a <typeparamref name="TPackage"/>.
/// </summary>
/// <typeparam name="TPackage">Type of the <see cref="OpenXmlPackage"/>.</typeparam>
public interface IPackageBuilder<TPackage>
where TPackage : OpenXmlPackage
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if NET7_0_OR_GREATER

using DocumentFormat.OpenXml.Packaging;

namespace DocumentFormat.OpenXml.Builder;

/// <summary>
/// An interface that exposes ability to create a builder for <typeparamref name="TPackage"/>.
/// </summary>
/// <typeparam name="TPackage">Type of <see cref="OpenXmlPackage"/>.</typeparam>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "Static abstract interface types")]
public interface IPackageDocumentBuilder<TPackage> where TPackage : OpenXmlPackage, IPackageDocumentBuilder<TPackage>
{
/// <summary>
/// Creates a default builder for <typeparamref name="TPackage"/>.
/// </summary>
/// <returns>The default builder.</returns>
static abstract IPackageBuilder<TPackage> CreateDefaultBuilder();

/// <summary>
/// Creates a builder that has minimal initialization for <typeparamref name="TPackage"/>.
/// </summary>
/// <returns>A minimal builder.</returns>
static abstract IPackageBuilder<TPackage> CreateBuilder();
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,68 @@

namespace DocumentFormat.OpenXml.Builder;

internal static class OpenXmlPackageBuilderExtensions
/// <summary>
/// A collection of extension methods for opening packages
/// </summary>
public static class OpenXmlPackageBuilderExtensions
{
/// <summary>
/// Opens the <paramref name="stream"/> with the given <paramref name="mode"/>.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is registered with package")]
public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, Stream stream, PackageOpenMode mode)
where TPackage : OpenXmlPackage
=> builder.Open(new StreamPackageFeature(stream, mode));
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

return builder.Open(new StreamPackageFeature(stream, mode));
}

/// <summary>
/// Opens the <paramref name="file"/> with the given <paramref name="mode"/>.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is registered with package")]
public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, string file, PackageOpenMode mode)
where TPackage : OpenXmlPackage
=> builder.Open(new FilePackageFeature(file, mode));
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, string file, bool isEditing)
return builder.Open(new FilePackageFeature(file, mode));
}

/// <summary>
/// Opens the <paramref name="package"/>.
/// </summary>
public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, System.IO.Packaging.Package package)
where TPackage : OpenXmlPackage
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

return builder.Open(new PackageFeature(package));
}

internal static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, string file, bool isEditing)
where TPackage : OpenXmlPackage
=> builder.Open(file, isEditing ? PackageOpenMode.ReadWrite : PackageOpenMode.Read);

public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, Stream stream, bool isEditing)
internal static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, Stream stream, bool isEditing)
where TPackage : OpenXmlPackage
=> builder.Open(stream, isEditing ? PackageOpenMode.ReadWrite : PackageOpenMode.Read);

[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is registered with package")]
public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder)
internal static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder)
where TPackage : OpenXmlPackage
=> builder.Open(new StreamPackageFeature(new MemoryStream(), PackageOpenMode.Create));

public static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, System.IO.Packaging.Package package)
where TPackage : OpenXmlPackage
=> builder.Open(new PackageFeature(package));

private static TPackage Open<TPackage>(this IPackageBuilder<TPackage> builder, IPackageInitializer initializer)
where TPackage : OpenXmlPackage
{
Expand All @@ -58,9 +91,24 @@ internal static IPackageBuilder<TPackage> Use<TPackage>(this IPackageBuilder<TPa
next(package);
});

/// <summary>
/// Adds the <paramref name="middleware"/> to the builder for initializing a package.
/// </summary>
public static IPackageBuilder<TPackage> Use<TPackage>(this IPackageBuilder<TPackage> builder, Action<TPackage, PackageInitializerDelegate<TPackage>> middleware)
where TPackage : OpenXmlPackage
=> builder.Use(next => package => middleware(package, next));
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

if (middleware is null)
{
throw new ArgumentNullException(nameof(middleware));
}

return builder.Use(next => package => middleware(package, next));
}

internal static IPackageBuilder<TPackage> UseSettings<TPackage>(this IPackageBuilder<TPackage> builder, OpenSettings settings)
where TPackage : OpenXmlPackage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace DocumentFormat.OpenXml.Features;
namespace DocumentFormat.OpenXml.Builder;

/// <summary>
/// An enum that describes how a package is going to be opened
/// </summary>
internal enum PackageOpenMode
public enum PackageOpenMode
{
/// <summary>
/// Indicates that a new package will be created.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Features;
using DocumentFormat.OpenXml.Packaging;
using System;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using System;
using System.IO;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Framework;
using DocumentFormat.OpenXml.Packaging;
using System;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Features;
using System.IO;
using System.IO.Packaging;
using System.Xml.Linq;
Expand Down
19 changes: 16 additions & 3 deletions src/DocumentFormat.OpenXml/Packaging/PresentationDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ namespace DocumentFormat.OpenXml.Packaging
/// Defines PresentationDocument - an OpenXmlPackage represents a Presentation document
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is returned")]
public partial class PresentationDocument : OpenXmlPackage
public partial class PresentationDocument :
#if NET7_0_OR_GREATER
OpenXmlPackage, IPackageDocumentBuilder<PresentationDocument>
#else
OpenXmlPackage
#endif
{
internal PresentationDocument()
: base()
Expand All @@ -23,9 +28,17 @@ internal PresentationDocument()

private static readonly IPackageBuilder<PresentationDocument> DefaultBuilder = new Builder().UseDefaultBehaviorAndLockBuilder();

internal static IPackageBuilder<PresentationDocument> CreateBuilder() => new Builder();
/// <summary>
/// Creates a default builder for <see cref="PresentationDocument"/>
/// </summary>
/// <returns>The default builder.</returns>
public static IPackageBuilder<PresentationDocument> CreateBuilder() => new Builder();

internal static IPackageBuilder<PresentationDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();
/// <summary>
/// Creates a builder that has minimal initialization for <see cref="PresentationDocument"/>.
/// </summary>
/// <returns>A minimal builder.</returns>
public static IPackageBuilder<PresentationDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();

private sealed class Builder : OpenXmlPackageBuilder<PresentationDocument>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Features;
using System.IO;
using System.IO.Packaging;
using System.Xml.Linq;
Expand Down
19 changes: 16 additions & 3 deletions src/DocumentFormat.OpenXml/Packaging/SpreadsheetDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ namespace DocumentFormat.OpenXml.Packaging
/// Defines SpreadsheetDocument - an OpenXmlPackage represents a Spreadsheet document.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is returned")]
public partial class SpreadsheetDocument : OpenXmlPackage
public partial class SpreadsheetDocument :
#if NET7_0_OR_GREATER
OpenXmlPackage, IPackageDocumentBuilder<SpreadsheetDocument>
#else
OpenXmlPackage
#endif
{
internal SpreadsheetDocument()
: base()
Expand All @@ -23,9 +28,17 @@ internal SpreadsheetDocument()

private static readonly IPackageBuilder<SpreadsheetDocument> DefaultBuilder = new Builder().UseDefaultBehaviorAndLockBuilder();

internal static IPackageBuilder<SpreadsheetDocument> CreateBuilder() => new Builder();
/// <summary>
/// Creates a default builder for <see cref="SpreadsheetDocument"/>
/// </summary>
/// <returns>The default builder.</returns>
public static IPackageBuilder<SpreadsheetDocument> CreateBuilder() => new Builder();

internal static IPackageBuilder<SpreadsheetDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();
/// <summary>
/// Creates a builder that has minimal initialization for <see cref="SpreadsheetDocument"/>.
/// </summary>
/// <returns>A minimal builder.</returns>
public static IPackageBuilder<SpreadsheetDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();

private sealed class Builder : OpenXmlPackageBuilder<SpreadsheetDocument>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Features;
using System.IO;
using System.IO.Packaging;
using System.Xml.Linq;
Expand Down
19 changes: 16 additions & 3 deletions src/DocumentFormat.OpenXml/Packaging/WordprocessingDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ namespace DocumentFormat.OpenXml.Packaging
/// Defines WordprocessingDocument - an OpenXmlPackage represents a Word document.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposable is returned")]
public partial class WordprocessingDocument : OpenXmlPackage
public partial class WordprocessingDocument :
#if NET7_0_OR_GREATER
OpenXmlPackage, IPackageDocumentBuilder<WordprocessingDocument>
#else
OpenXmlPackage
#endif
{
internal WordprocessingDocument()
: base()
Expand All @@ -24,9 +29,17 @@ internal WordprocessingDocument()

private static readonly IPackageBuilder<WordprocessingDocument> DefaultBuilder = new Builder().UseDefaultBehaviorAndLockBuilder();

internal static IPackageBuilder<WordprocessingDocument> CreateBuilder() => new Builder();
/// <summary>
/// Creates a default builder for <see cref="WordprocessingDocument"/>
/// </summary>
/// <returns>The default builder.</returns>
public static IPackageBuilder<WordprocessingDocument> CreateBuilder() => new Builder();

internal static IPackageBuilder<WordprocessingDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();
/// <summary>
/// Creates a builder that has minimal initialization for <see cref="WordprocessingDocument"/>.
/// </summary>
/// <returns>A minimal builder.</returns>
public static IPackageBuilder<WordprocessingDocument> CreateDefaultBuilder() => DefaultBuilder.Clone();

private sealed class Builder : OpenXmlPackageBuilder<WordprocessingDocument>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using DocumentFormat.OpenXml.Builder;
using DocumentFormat.OpenXml.Packaging;
using NSubstitute;
using System;
Expand Down

0 comments on commit 3976cf1

Please sign in to comment.