Skip to content

Commit 7f0f8fc

Browse files
committed
make factory struct
1 parent be53c40 commit 7f0f8fc

File tree

2 files changed

+36
-85
lines changed

2 files changed

+36
-85
lines changed

src/DocumentFormat.OpenXml.Framework/Framework/Metadata/ElementFactory.cs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,12 @@
44
using System;
55
using System.Diagnostics;
66

7-
namespace DocumentFormat.OpenXml.Framework.Metadata
8-
{
9-
[DebuggerDisplay("{QName,nq}")]
10-
internal sealed class ElementFactory
11-
{
12-
private readonly Func<OpenXmlElement> _factory;
13-
14-
public ElementFactory(in OpenXmlSchemaType type, Func<OpenXmlElement> factory)
15-
{
16-
Type = type;
17-
_factory = factory;
18-
}
19-
20-
public OpenXmlSchemaType Type { get; }
7+
namespace DocumentFormat.OpenXml.Framework.Metadata;
218

22-
public OpenXmlElement Create() => _factory();
23-
24-
public static ElementFactory Create<T>()
25-
where T : OpenXmlElement, new()
26-
{
27-
var instance = new T();
9+
[DebuggerDisplay("{QName,nq}")]
10+
internal readonly struct ElementFactory(OpenXmlSchemaType type, Func<OpenXmlElement> factory)
11+
{
12+
public OpenXmlSchemaType Type => type;
2813

29-
return new ElementFactory(instance.Metadata.Type, static () => new T());
30-
}
31-
}
14+
public OpenXmlElement Create() => factory();
3215
}
Lines changed: 30 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,49 @@
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 System;
54
using System.Collections.Generic;
6-
using System.Linq;
75

8-
namespace DocumentFormat.OpenXml.Framework.Metadata
6+
namespace DocumentFormat.OpenXml.Framework.Metadata;
7+
8+
/// <summary>
9+
/// A lookup that identifies properties on an <see cref="OpenXmlElement"/> and caches the schema information
10+
/// from those elements.
11+
/// </summary>
12+
internal class ElementFactoryCollection
913
{
10-
/// <summary>
11-
/// A lookup that identifies properties on an <see cref="OpenXmlElement"/> and caches the schema information
12-
/// from those elements.
13-
/// </summary>
14-
internal class ElementFactoryCollection
15-
{
16-
public static readonly ElementFactoryCollection Empty = new(Enumerable.Empty<ElementFactory>());
14+
public static readonly ElementFactoryCollection Empty = new([]);
1715

18-
private readonly ElementFactory[] _data;
16+
private readonly List<ElementFactory> _data;
1917

20-
public ElementFactoryCollection(IEnumerable<ElementFactory> lookup)
21-
{
22-
var array = lookup.ToArray();
23-
24-
Array.Sort(array, ElementChildNameComparer.Instance);
18+
public ElementFactoryCollection(List<ElementFactory> lookup)
19+
{
20+
lookup.Sort(ElementChildNameComparer.Instance);
21+
_data = lookup;
22+
}
2523

26-
_data = array;
24+
public OpenXmlElement? Create(in OpenXmlQualifiedName qname)
25+
{
26+
if (_data.Count == 0)
27+
{
28+
return null;
2729
}
2830

29-
public int Count => _data.Length;
31+
// This is on a hot-path and using a dictionary adds substantial time to the lookup. Most child lists are small, so using a sorted
32+
// list to store them with a binary search improves overall performance.
33+
var idx = _data.BinarySearch(new ElementFactory(new(qname, default), null!), ElementChildNameComparer.Instance);
3034

31-
public IEnumerable<ElementFactory> Elements => _data;
32-
33-
public OpenXmlElement? Create(in OpenXmlQualifiedName qname)
35+
if (idx < 0)
3436
{
35-
if (_data.Length == 0)
36-
{
37-
return null;
38-
}
39-
40-
// This is on a hot-path and using a dictionary adds substantial time to the lookup. Most child lists are small, so using a sorted
41-
// list to store them with a binary search improves overall performance.
42-
var idx = Array.BinarySearch(_data, new ElementFactory(new(qname, default), null!), ElementChildNameComparer.Instance);
43-
44-
if (idx < 0)
45-
{
46-
return null;
47-
}
48-
49-
return _data[idx].Create();
37+
return null;
5038
}
5139

52-
private class ElementChildNameComparer : IComparer<ElementFactory>
53-
{
54-
public static IComparer<ElementFactory> Instance { get; } = new ElementChildNameComparer();
55-
56-
private ElementChildNameComparer()
57-
{
58-
}
59-
60-
public int Compare(ElementFactory? x, ElementFactory? y)
61-
{
62-
if (x is null && y is null)
63-
{
64-
return 0;
65-
}
66-
67-
if (x is null)
68-
{
69-
return -1;
70-
}
40+
return _data[idx].Create();
41+
}
7142

72-
if (y is null)
73-
{
74-
return 1;
75-
}
43+
private sealed class ElementChildNameComparer : IComparer<ElementFactory>
44+
{
45+
public static IComparer<ElementFactory> Instance { get; } = new ElementChildNameComparer();
7646

77-
return x.Type.Name.CompareTo(y.Type.Name);
78-
}
79-
}
47+
public int Compare(ElementFactory x, ElementFactory y) => x.Type.Name.CompareTo(y.Type.Name);
8048
}
8149
}

0 commit comments

Comments
 (0)