Skip to content

Commit 06a66f0

Browse files
Optimized write adapters and improved code clarity (#940)
* Optimized IEnumerable<CellWriteInfo> to CellWriteInfo[] for all writeadapters * Renaming all "props" variables to "mappings" for clarity * Added NetStandardExtensions class to replicate .NET framework's helper methods and reduce code clutter * Added .editorconfig for src folder to solution --------- Signed-off-by: Michele Bastione <michele.bastione@gmail.com>
1 parent 6c5cb81 commit 06a66f0

18 files changed

Lines changed: 240 additions & 244 deletions

MiniExcel.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<File Path="docs\README.zh-Hant.md" />
2626
</Folder>
2727
<Folder Name="/src/">
28+
<File Path="src/.editorconfig" />
2829
<File Path="src\Directory.Build.props" />
2930
<File Path="src\Directory.Packages.props" />
3031
<Project Path="src\MiniExcel.OpenXml/MiniExcel.OpenXml.csproj" />

src/.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dotnet_diagnostic.CA1835.severity = error
66
# CA1849: Call async methods when in an async method
77
dotnet_diagnostic.CA1849.severity = error
88

9+
# CA2000: Dispose objects before losing scope
910
dotnet_diagnostic.CA2000.severity = error
1011

1112
# CA2007: Do not directly await a Task

src/MiniExcel.Core/Abstractions/IMiniExcelWriteAdapter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ public interface IMiniExcelWriteAdapter
44
{
55
bool TryGetKnownCount(out int count);
66
List<MiniExcelColumnMapping>? GetColumns();
7-
IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<MiniExcelColumnMapping> props, CancellationToken cancellationToken = default);
7+
IEnumerable<CellWriteInfo[]> GetRows(List<MiniExcelColumnMapping> mappings, CancellationToken cancellationToken = default);
88
}
99

10-
public readonly struct CellWriteInfo(object? value, int cellIndex, MiniExcelColumnMapping prop)
10+
public readonly struct CellWriteInfo(object? value, int cellIndex, MiniExcelColumnMapping? mapping)
1111
{
1212
public object? Value { get; } = value;
1313
public int CellIndex { get; } = cellIndex;
14-
public MiniExcelColumnMapping Prop { get; } = prop;
15-
}
14+
public MiniExcelColumnMapping? Mapping { get; } = mapping;
15+
}

src/MiniExcel.Core/Abstractions/IMiniExcelWriteAdapterAsync.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
public interface IMiniExcelWriteAdapterAsync
44
{
55
Task<List<MiniExcelColumnMapping>?> GetColumnsAsync();
6-
IAsyncEnumerable<CellWriteInfo[]> GetRowsAsync(List<MiniExcelColumnMapping> props, CancellationToken cancellationToken);
6+
IAsyncEnumerable<CellWriteInfo[]> GetRowsAsync(List<MiniExcelColumnMapping> mappings, CancellationToken cancellationToken);
77
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace MiniExcelLib.Core.Helpers;
2+
3+
public static class NetStandardExtensions
4+
{
5+
#if NETSTANDARD2_0
6+
public static TValue? GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key, TValue? defaultValue = default)
7+
{
8+
return dictionary.TryGetValue(key, out var value) ? value : defaultValue;
9+
}
10+
#endif
11+
}

src/MiniExcel.Core/Reflection/ColumnMappingsProvider.cs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ internal static List<MiniExcelColumnMapping> GetMappingsForImport(Type type, str
4848

4949
private static List<MiniExcelColumnMapping?> GetMappingsForExport(this Type type, MiniExcelBaseConfiguration configuration)
5050
{
51-
var props = GetColumnMappings(type, ExportMembersFlags, configuration)
51+
var mappings = GetColumnMappings(type, ExportMembersFlags, configuration)
5252
.Where(prop => prop?.MemberAccessor.CanRead is true)
5353
.ToList();
5454

55-
if (props.Count == 0)
55+
if (mappings.Count == 0)
5656
throw new InvalidMappingException($"{type.Name} must contain at least one mappable property or field.", type);
5757

58-
return SortMappings(props);
58+
return SortMappings(mappings);
5959
}
6060

6161
private static List<MiniExcelColumnMapping?> SortMappings(List<MiniExcelColumnMapping?> mappings)
@@ -81,29 +81,29 @@ internal static List<MiniExcelColumnMapping> GetMappingsForImport(Type type, str
8181
if (explicitIndexMappings.Count != 0)
8282
maxColumnIndex = Math.Max(explicitIndexMappings.Max(w => w?.ExcelColumnIndex ?? 0), maxColumnIndex);
8383

84-
var withoutCustomIndexProps = mappings
84+
var mappingsWithoutCustomIndex = mappings
8585
.Where(w => w?.ExcelColumnIndex is null or -1)
8686
.ToList();
8787

8888
var index = 0;
89-
var newProps = new List<MiniExcelColumnMapping?>();
89+
var newMappings = new List<MiniExcelColumnMapping?>();
9090
for (int i = 0; i <= maxColumnIndex; i++)
9191
{
9292
if (explicitIndexMappings.SingleOrDefault(s => s?.ExcelColumnIndex == i) is { } p1)
9393
{
94-
newProps.Add(p1);
94+
newMappings.Add(p1);
9595
}
9696
else
9797
{
98-
var p2 = withoutCustomIndexProps.ElementAtOrDefault(index);
98+
var map = mappingsWithoutCustomIndex.ElementAtOrDefault(index);
9999

100-
p2?.ExcelColumnIndex = i;
101-
newProps.Add(p2);
100+
map?.ExcelColumnIndex = i;
101+
newMappings.Add(map);
102102

103103
index++;
104104
}
105105
}
106-
return newProps;
106+
return newMappings;
107107
}
108108

109109
private static IEnumerable<MiniExcelColumnMapping?> GetColumnMappings(Type type, BindingFlags bindingFlags, MiniExcelBaseConfiguration configuration)
@@ -156,23 +156,23 @@ internal static List<MiniExcelColumnMapping> GetMappingsForImport(Type type, str
156156

157157
private static List<MiniExcelColumnMapping?> GetDictionaryColumnInfo(IDictionary<string, object?>? dicString, IDictionary? dic, MiniExcelBaseConfiguration configuration)
158158
{
159-
var props = new List<MiniExcelColumnMapping?>();
159+
var mappings = new List<MiniExcelColumnMapping?>();
160160

161161
var keys = dicString?.Keys.ToList()
162162
?? dic?.Keys
163163
?? throw new InvalidOperationException();
164164

165165
foreach (var key in keys)
166166
{
167-
SetDictionaryColumnInfo(props, key, configuration);
167+
SetDictionaryColumnInfo(mappings, key, configuration);
168168
}
169169

170-
return SortMappings(props);
170+
return SortMappings(mappings);
171171
}
172172

173-
private static void SetDictionaryColumnInfo(List<MiniExcelColumnMapping?> props, object key, MiniExcelBaseConfiguration configuration)
173+
private static void SetDictionaryColumnInfo(List<MiniExcelColumnMapping?> mappings, object key, MiniExcelBaseConfiguration configuration)
174174
{
175-
var mapping = new MiniExcelColumnMapping
175+
var map = new MiniExcelColumnMapping
176176
{
177177
Key = key,
178178
ExcelColumnName = key?.ToString()
@@ -185,40 +185,40 @@ private static void SetDictionaryColumnInfo(List<MiniExcelColumnMapping?> props,
185185
var dynamicColumn = configuration.DynamicColumns.SingleOrDefault(x => x.Key == key?.ToString());
186186
if (dynamicColumn is not null)
187187
{
188-
mapping.Nullable = true;
188+
map.Nullable = true;
189189

190190
if (dynamicColumn is { Format: { } fmt, FormatId: var fmtId })
191191
{
192-
mapping.ExcelFormat = fmt;
193-
mapping.ExcelFormatId = fmtId;
192+
map.ExcelFormat = fmt;
193+
map.ExcelFormatId = fmtId;
194194
}
195195

196196
if (dynamicColumn.Aliases is { } aliases)
197-
mapping.ExcelColumnAliases = aliases;
197+
map.ExcelColumnAliases = aliases;
198198

199199
if (dynamicColumn.IndexName is { } idxName)
200-
mapping.ExcelIndexName = idxName;
200+
map.ExcelIndexName = idxName;
201201

202202
if (dynamicColumn.Name is { } colName)
203-
mapping.ExcelColumnName = colName;
203+
map.ExcelColumnName = colName;
204204

205-
mapping.ExcelColumnIndex = dynamicColumn.Index;
206-
mapping.ExcelColumnWidth = dynamicColumn.Width;
207-
mapping.ExcelHiddenColumn = dynamicColumn.Hidden;
208-
mapping.ExcelColumnType = dynamicColumn.Type;
209-
mapping.CustomFormatter = dynamicColumn.CustomFormatter;
205+
map.ExcelColumnIndex = dynamicColumn.Index;
206+
map.ExcelColumnWidth = dynamicColumn.Width;
207+
map.ExcelHiddenColumn = dynamicColumn.Hidden;
208+
map.ExcelColumnType = dynamicColumn.Type;
209+
map.CustomFormatter = dynamicColumn.CustomFormatter;
210210

211211
isIgnore = dynamicColumn.Ignore;
212212
}
213213
}
214214

215215
if (!isIgnore)
216-
props.Add(mapping);
216+
mappings.Add(map);
217217
}
218218

219-
internal static bool TryGetColumnMappings(Type? type, MiniExcelBaseConfiguration configuration, out List<MiniExcelColumnMapping?> props)
219+
internal static bool TryGetColumnMappings(Type? type, MiniExcelBaseConfiguration configuration, out List<MiniExcelColumnMapping?> mappings)
220220
{
221-
props = [];
221+
mappings = [];
222222

223223
// Unknown type
224224
if (type is null)
@@ -230,7 +230,7 @@ internal static bool TryGetColumnMappings(Type? type, MiniExcelBaseConfiguration
230230
if (ValueIsNeededToDetermineProperties(type))
231231
return false;
232232

233-
props = type.GetMappingsForExport(configuration);
233+
mappings = type.GetMappingsForExport(configuration);
234234
return true;
235235
}
236236

src/MiniExcel.Core/WriteAdapters/AsyncEnumerableWriteAdapter.cs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ internal sealed class AsyncEnumerableWriteAdapter<T>(IAsyncEnumerable<T> values,
2727
return ColumnMappingsProvider.GetColumnMappingFromValue(_enumerator.Current, _configuration);
2828
}
2929

30-
public async IAsyncEnumerable<CellWriteInfo[]> GetRowsAsync(List<MiniExcelColumnMapping> props, [EnumeratorCancellation] CancellationToken cancellationToken)
30+
public async IAsyncEnumerable<CellWriteInfo[]> GetRowsAsync(List<MiniExcelColumnMapping> mappings, [EnumeratorCancellation] CancellationToken cancellationToken)
3131
{
3232
if (_empty)
3333
yield break;
@@ -44,30 +44,27 @@ public async IAsyncEnumerable<CellWriteInfo[]> GetRowsAsync(List<MiniExcelColumn
4444
do
4545
{
4646
cancellationToken.ThrowIfCancellationRequested();
47-
yield return GetRowValues(_enumerator.Current, props);
47+
yield return GetRowValues(_enumerator.Current, mappings);
4848
}
4949
while (await _enumerator.MoveNextAsync().ConfigureAwait(false));
5050
}
5151

52-
private static CellWriteInfo[] GetRowValues(T currentValue, List<MiniExcelColumnMapping> props)
52+
private static CellWriteInfo[] GetRowValues(T currentValue, List<MiniExcelColumnMapping?> mappings)
5353
{
5454
var column = 0;
55-
var result = new List<CellWriteInfo>();
55+
var result = new List<CellWriteInfo>(mappings.Count);
5656

57-
foreach (var prop in props)
57+
foreach (var map in mappings)
5858
{
5959
column++;
60-
61-
if (prop is null)
62-
continue;
63-
64-
var info = currentValue switch
60+
var cellValue = currentValue switch
6561
{
66-
IDictionary<string, object> genericDictionary => new CellWriteInfo(genericDictionary[prop.Key.ToString()], column, prop),
67-
IDictionary dictionary => new CellWriteInfo(dictionary[prop.Key], column, prop),
68-
_ => new CellWriteInfo(prop.MemberAccessor.GetValue(currentValue), column, prop)
62+
_ when map is null => null,
63+
IDictionary<string, object> genericDictionary => genericDictionary[map.Key.ToString()],
64+
IDictionary dictionary => dictionary[map.Key],
65+
_ => map.MemberAccessor.GetValue(currentValue)
6966
};
70-
result.Add(info);
67+
result.Add(new CellWriteInfo(cellValue, column, map));
7168
}
7269

7370
return result.ToArray();
@@ -84,4 +81,4 @@ public async ValueTask DisposeAsync()
8481
_disposed = true;
8582
}
8683
}
87-
}
84+
}

src/MiniExcel.Core/WriteAdapters/DataReaderWriteAdapter.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,48 @@ public bool TryGetKnownCount(out int count)
1313

1414
public List<MiniExcelColumnMapping> GetColumns()
1515
{
16-
var props = new List<MiniExcelColumnMapping>();
16+
var mappings = new List<MiniExcelColumnMapping>();
1717
for (var i = 0; i < _reader.FieldCount; i++)
1818
{
1919
var columnName = _reader.GetName(i);
2020
if (!_configuration.DynamicColumnFirst ||
2121
_configuration.DynamicColumns.Any(d => string.Equals(d.Key, columnName, StringComparison.OrdinalIgnoreCase)))
2222
{
23-
var prop = ColumnMappingsProvider.GetColumnMappingFromDynamicConfiguration(columnName, _configuration);
24-
props.Add(prop);
23+
var map = ColumnMappingsProvider.GetColumnMappingFromDynamicConfiguration(columnName, _configuration);
24+
mappings.Add(map);
2525
}
2626
}
27-
return props;
27+
return mappings;
2828
}
2929

30-
public IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<MiniExcelColumnMapping> props, CancellationToken cancellationToken = default)
30+
public IEnumerable<CellWriteInfo[]> GetRows(List<MiniExcelColumnMapping> mappings, CancellationToken cancellationToken = default)
3131
{
3232
while (_reader.Read())
3333
{
3434
cancellationToken.ThrowIfCancellationRequested();
35-
yield return GetRowValues(props);
35+
yield return GetRowValues(mappings);
3636
}
3737
}
3838

39-
private IEnumerable<CellWriteInfo> GetRowValues(List<MiniExcelColumnMapping> props)
39+
private CellWriteInfo[] GetRowValues(List<MiniExcelColumnMapping> mappings)
4040
{
4141
var column = 1;
42+
var result = new List<CellWriteInfo>(mappings.Count);
43+
4244
for (int i = 0; i < _reader.FieldCount; i++)
4345
{
44-
var prop = props[i];
45-
if (prop is { ExcelIgnoreColumn: false })
46+
var map = mappings[i];
47+
if (map is not { ExcelIgnoreColumn: true })
4648
{
4749
var columnIndex = _configuration.DynamicColumnFirst
48-
? _reader.GetOrdinal(prop.Key.ToString())
50+
? _reader.GetOrdinal(map.Key.ToString())
4951
: i;
50-
51-
yield return new CellWriteInfo(_reader.GetValue(columnIndex), column, prop);
52+
53+
result.Add(new CellWriteInfo(_reader.GetValue(columnIndex), column, map));
5254
column++;
5355
}
5456
}
57+
58+
return result.ToArray();
5559
}
56-
}
60+
}

src/MiniExcel.Core/WriteAdapters/DataTableWriteAdapter.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,32 @@ public bool TryGetKnownCount(out int count)
1313

1414
public List<MiniExcelColumnMapping> GetColumns()
1515
{
16-
var props = new List<MiniExcelColumnMapping>();
16+
var mappings = new List<MiniExcelColumnMapping>();
1717
for (var i = 0; i < _dataTable.Columns.Count; i++)
1818
{
1919
var columnName = _dataTable.Columns[i].Caption ?? _dataTable.Columns[i].ColumnName;
20-
var prop = ColumnMappingsProvider.GetColumnMappingFromDynamicConfiguration(columnName, _configuration);
21-
props.Add(prop);
20+
var map = ColumnMappingsProvider.GetColumnMappingFromDynamicConfiguration(columnName, _configuration);
21+
mappings.Add(map);
2222
}
23-
return props;
23+
return mappings;
2424
}
2525

26-
public IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<MiniExcelColumnMapping> props, CancellationToken cancellationToken = default)
26+
public IEnumerable<CellWriteInfo[]> GetRows(List<MiniExcelColumnMapping> mappings, CancellationToken cancellationToken = default)
2727
{
2828
for (int row = 0; row < _dataTable.Rows.Count; row++)
2929
{
3030
cancellationToken.ThrowIfCancellationRequested();
31-
yield return GetRowValues(row, props);
31+
yield return GetRowValues(row, mappings);
3232
}
3333
}
3434

35-
private IEnumerable<CellWriteInfo> GetRowValues(int row, List<MiniExcelColumnMapping> props)
35+
private CellWriteInfo[] GetRowValues(int row, List<MiniExcelColumnMapping> mappings)
3636
{
37+
var result = new List<CellWriteInfo>(mappings.Count);
3738
for (int i = 0, column = 1; i < _dataTable.Columns.Count; i++, column++)
3839
{
39-
yield return new CellWriteInfo(_dataTable.Rows[row][i], column, props[i]);
40+
result.Add(new CellWriteInfo(_dataTable.Rows[row][i], column, mappings[i]));
4041
}
42+
return result.ToArray();
4143
}
42-
}
44+
}

0 commit comments

Comments
 (0)