Created
November 1, 2023 16:37
-
-
Save lucasteles/bc0f132c02e1caa4201326d35b257a5e to your computer and use it in GitHub Desktop.
DynamicProperties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using System.Collections.Generic; | |
using System.Collections; | |
using System.Text.Json; | |
using static System.Console; | |
Document[] docs = | |
{ | |
new( | |
new(DocumentColumnType.Number, "Foo", "42"), | |
new(DocumentColumnType.Number, "Bar", "69", 1), | |
new(DocumentColumnType.String, "Xablau", "morango", 2) | |
), | |
new( | |
new(DocumentColumnType.Number, "Foo", "99"), | |
new(DocumentColumnType.Number, "Bar", "X", 1), | |
new(DocumentColumnType.String, "Truth", "tax is theft", 2) | |
), | |
new( | |
new(DocumentColumnType.String, "Foo", "4 8 15 16 23 42"), | |
new(DocumentColumnType.Date, "Birth", "1990-12-11", 2) | |
), | |
}; | |
WriteLine(""" | |
---------------- | |
CSV File: | |
---------------- | |
"""); | |
WriteLine(Document.ToCSV(docs)); | |
WriteLine(); | |
WriteLine(""" | |
---------------- | |
JSON File: | |
---------------- | |
"""); | |
WriteLine(Document.ToJson(docs)); | |
public enum DocumentColumnType | |
{ | |
String, | |
Number, | |
Date, | |
}; | |
public record DocumentColumn( | |
DocumentColumnType Type, | |
string Column, | |
string Value, | |
int Order = 0 | |
) | |
{ | |
public object FormattedValue => | |
Type switch | |
{ | |
DocumentColumnType.String => Value.Trim(), | |
DocumentColumnType.Number => | |
long.TryParse(Value, out var value) ? value : "NaN", | |
DocumentColumnType.Date => | |
DateOnly.TryParse(Value, out var value) ? value : string.Empty, | |
_ => throw new ArgumentOutOfRangeException(), | |
}; | |
} | |
public sealed class Document | |
{ | |
public Guid Id { get; init; } = Guid.NewGuid(); | |
public IReadOnlyDictionary<string, DocumentColumn> Columns { get; } | |
public Document(params DocumentColumn[] columns) => | |
Columns = columns.ToDictionary(x => x.Column, x => x); | |
public object? this[string nome] => | |
Columns.TryGetValue(nome, out var value) ? value.FormattedValue : null; | |
public IDictionary<string, object> ToDict() => | |
Columns.Values | |
.OrderBy(x => x.Order).ThenBy(x => x.Column) | |
.ToDictionary(x => x.Column, x => x.FormattedValue); | |
public IEnumerable<object> GetValues(IEnumerable<string>? columns = null) | |
{ | |
columns ??= Columns.Values | |
.OrderBy(x => x.Order).ThenBy(x => x.Column) | |
.Select(x => x.Column) | |
.ToArray(); | |
return columns.Select(name => this[name] ?? string.Empty); | |
} | |
public static JsonElement ToJson(IEnumerable<Document> docs) => | |
JsonSerializer.SerializeToElement( | |
docs.Select(d => d.ToDict()), | |
new JsonSerializerOptions | |
{ | |
WriteIndented = true, | |
}); | |
public static string ToCSV(IReadOnlyCollection<Document> docs, char delimiter = ';') | |
{ | |
var columns = docs | |
.SelectMany(x => x.Columns.Values) | |
.OrderBy(x => x.Order).ThenBy(x => x.Column) | |
.Select(x => x.Column) | |
.Distinct() | |
.ToArray(); | |
var header = string.Join(delimiter, columns); | |
var values = docs | |
.Select(cols => cols.GetValues(columns)) | |
.Select(values => string.Join(delimiter, values)); | |
return string.Join(Environment.NewLine, values.Prepend(header)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment