Skip to content

Instantly share code, notes, and snippets.

@lucasteles
Created November 1, 2023 16:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucasteles/bc0f132c02e1caa4201326d35b257a5e to your computer and use it in GitHub Desktop.
Save lucasteles/bc0f132c02e1caa4201326d35b257a5e to your computer and use it in GitHub Desktop.
DynamicProperties
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