Skip to content

Commit ee2bbfc

Browse files
authored
Add a strongly typed layer for parts and elements (#1185)
1 parent 5c9d418 commit ee2bbfc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+364
-52
lines changed

gen/DocumentFormat.OpenXml.Generator.Models/Generators/Elements/DataModelWriterExtensions.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ namespace DocumentFormat.OpenXml.Generator.Generators.Elements;
1111

1212
public static class DataModelWriterExtensions
1313
{
14+
private static HashSet<string> _typedBasedClasses = new()
15+
{
16+
"OpenXmlElement",
17+
"OpenXmlCompositeElement",
18+
"OpenXmlLeafElement",
19+
"OpenXmlLeafTextElement",
20+
"OpenXmlPartRootElement",
21+
};
22+
1423
public static bool GetDataModelSyntax(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaNamespace model)
1524
{
1625
foreach (var ns in GetNamespaces(model, services).Distinct().OrderBy(n => n))
@@ -53,6 +62,21 @@ public static bool GetDataModelSyntax(this IndentedTextWriter writer, OpenXmlGen
5362
return delimiter.Count > 0;
5463
}
5564

65+
private static string GetBaseName(SchemaType type)
66+
{
67+
if (type.IsPart)
68+
{
69+
return "TypedOpenXmlPartRootElement";
70+
}
71+
72+
if (_typedBasedClasses.Contains(type.BaseClass))
73+
{
74+
return $"Typed{type.BaseClass}";
75+
}
76+
77+
return type.BaseClass;
78+
}
79+
5680
private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorServices services, SchemaType element)
5781
{
5882
writer.WriteDocumentationComment(BuildTypeComments(services, element));
@@ -69,7 +93,7 @@ private static void WriteType(this IndentedTextWriter writer, OpenXmlGeneratorSe
6993
writer.Write("partial class ");
7094
writer.Write(className);
7195
writer.Write(" : ");
72-
writer.WriteLine(element.IsPart ? "OpenXmlPartRootElement" : element.BaseClass);
96+
writer.WriteLine(GetBaseName(element));
7397

7498
using (writer.AddBlock(new() { AddNewLineBeforeClosing = true, IncludeTrailingNewline = false }))
7599
{

gen/DocumentFormat.OpenXml.Generator.Models/Generators/Parts/PartWriter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public static void WritePart(this IndentedTextWriter writer, OpenXmlGeneratorSer
4949
writer.Write("public partial class ");
5050
writer.Write(type.Name);
5151
writer.Write(" : ");
52+
5253
writer.Write(type.Base);
5354

5455
if (type.HasFixedContent)

gen/DocumentFormat.OpenXml.Generator.Models/Models/Part.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ namespace DocumentFormat.OpenXml.Generator.Models;
55

66
public class Part
77
{
8+
private string _base = null!;
9+
810
public string Name { get; set; } = null!;
911

10-
public string Base { get; set; } = null!;
12+
public string Base
13+
{
14+
get => _base;
15+
set => _base = value.Equals("OpenXmlPart") ? "TypedOpenXmlPart" : value;
16+
}
1117

1218
public bool HasFixedContent => ContentType is not null;
1319

src/DocumentFormat.OpenXml/AlternateContentChoice.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace DocumentFormat.OpenXml
1212
/// </summary>
1313
public class AlternateContentChoice : OpenXmlCompositeElement
1414
{
15+
internal static OpenXmlQualifiedName InternalQName => new(AlternateContent.InternalQName.Namespace.Uri, Name);
16+
1517
private const string Name = "Choice";
1618

1719
/// <summary>

src/DocumentFormat.OpenXml/AlternateContentFallback.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace DocumentFormat.OpenXml
1212
/// </summary>
1313
public class AlternateContentFallback : OpenXmlCompositeElement
1414
{
15+
internal static OpenXmlQualifiedName InternalQName => new(AlternateContent.InternalQName.Namespace.Uri, Name);
16+
1517
private const string Name = "Fallback";
1618

1719
/// <summary>

src/DocumentFormat.OpenXml/Features/DefaultFeatures.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using DocumentFormat.OpenXml.Framework.Metadata;
45
using System;
56

67
namespace DocumentFormat.OpenXml.Features
@@ -14,6 +15,8 @@ internal partial class DefaultFeatures : IFeatureCollection
1415
public int Revision => 0;
1516

1617
[KnownFeature(typeof(IOpenXmlNamespaceIdResolver), typeof(OpenXmlNamespaceIdResolver))]
18+
[KnownFeature(typeof(IOpenXmlNamespaceResolver), typeof(NoDataNamespaceResolver))]
19+
[KnownFeature(typeof(IElementMetadataFactoryFeature), typeof(ElementMetadataFactoryFeature))]
1720
[ThreadSafe]
1821
public partial TFeature? Get<TFeature>();
1922

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using DocumentFormat.OpenXml.Framework;
5+
using DocumentFormat.OpenXml.Framework.Metadata;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Xml;
9+
10+
namespace DocumentFormat.OpenXml.Features
11+
{
12+
internal class NoDataNamespaceResolver : IOpenXmlNamespaceResolver
13+
{
14+
public IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope) => new Dictionary<string, string>();
15+
16+
public FileFormatVersions GetVersion(OpenXmlNamespace ns) => FileFormatVersions.Office2007;
17+
18+
public string? LookupNamespace(string prefix) => null;
19+
20+
public string? LookupPrefix(string namespaceName) => null;
21+
22+
public bool TryGetExtendedNamespace(OpenXmlNamespace ns, out OpenXmlNamespace extNamespaceUri)
23+
{
24+
extNamespaceUri = default;
25+
return false;
26+
}
27+
28+
public bool TryGetTransitionalNamespace(OpenXmlNamespace ns, out OpenXmlNamespace transitionalNamespace)
29+
{
30+
transitionalNamespace = default;
31+
return false;
32+
}
33+
34+
public bool TryGetTransitionalRelationship(OpenXmlNamespace ns, out OpenXmlNamespace transitionalRelationship)
35+
{
36+
transitionalRelationship = default;
37+
return false;
38+
}
39+
}
40+
}

src/DocumentFormat.OpenXml/Features/TypedFeatures.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public static IFeatureCollection Shared
3232
[KnownFeature(typeof(IRootElementFactory), typeof(ReflectionBasedRootElementFactory))]
3333
[KnownFeature(typeof(IPartMetadataFeature), typeof(CachedPartMetadataProvider))]
3434
[KnownFeature(typeof(IOpenXmlNamespaceResolver), typeof(OpenXmlNamespaceResolver))]
35-
[KnownFeature(typeof(IElementMetadataFactoryFeature), typeof(TypedElementMetadataFactoryFeature))]
3635
[KnownFeature(typeof(IPartFactory), typeof(ReflectionPartFactory))]
3736
[DelegatedFeature(nameof(FeatureCollection.Default), typeof(FeatureCollection))]
3837
[ThreadSafe]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace DocumentFormat.OpenXml.Framework.Metadata
1010
{
11-
internal class TypedElementMetadataFactoryFeature : IElementMetadataFactoryFeature
11+
internal class ElementMetadataFactoryFeature : IElementMetadataFactoryFeature
1212
{
1313
private readonly ConcurrentDictionary<Type, ElementMetadata> _lookup = new(new[]
1414
{

src/DocumentFormat.OpenXml/OpenXmlCompositeElement.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ namespace DocumentFormat.OpenXml
1919
/// </summary>
2020
public abstract class OpenXmlCompositeElement : OpenXmlElement
2121
{
22+
private protected const string UseGenericVersion = "Should use the generic version of this. This overload will be removed in a future version.";
23+
2224
private OpenXmlElement? _lastChild;
2325

2426
/// <summary>
@@ -42,7 +44,7 @@ protected OpenXmlCompositeElement(string outerXml)
4244
/// Initializes a new instance of the OpenXmlCompositeElement class using the supplied collection of elements.
4345
/// </summary>
4446
/// <param name="childrenElements">A collection of elements.</param>
45-
[Obsolete("Should use the generic version of this. This overload will be removed in a future version.")]
47+
[Obsolete(UseGenericVersion)]
4648
protected OpenXmlCompositeElement(IEnumerable childrenElements)
4749
: this()
4850
{

0 commit comments

Comments
 (0)