Files
elwig/Elwig/Models/Dtos/DataTable.cs

88 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Elwig.Models.Dtos {
public class DataTable<T> {
public string Name { get; set; }
public string FullName { get; set; }
public string? Subtitle { get; set; }
public IEnumerable<T> Rows { get; private set; }
public int RowNum => Rows.Count();
public int ColNum => ColumnNames.Count();
public IEnumerable<(string, Type?)> ColumnDefs => _map.Select(m => (m.Item1, m.Item2?.PropertyType ?? m.Item3?.FieldType));
public IEnumerable<string> ColumnNames => ColumnDefs.Select(m => m.Item1);
public IEnumerable<Type?> ColumnTypes => ColumnDefs.Select(m => m.Item2);
public IEnumerable<Type?> ColumnFlatTypes { get; private set; }
public IEnumerable<int> ColumnSpans { get; private set; }
public IEnumerable<int?> ColumnWidths { get; private set; }
public IEnumerable<string?[]> ColumnUnits { get; private set; }
private readonly PropertyInfo[] _properties;
private readonly FieldInfo[] _fields;
private readonly (string, PropertyInfo?, FieldInfo?)[] _map;
public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?, int?)>? colNames = null) {
_fields = typeof(T).GetFields();
_properties = typeof(T).GetProperties();
colNames ??= _properties.Select(p => p.Name).Union(_fields.Select(f => f.Name)).Select(i => (i, i, (string?)null, (int?)null)).ToList();
_map = colNames.Select(n => (n.Item2, _properties.FirstOrDefault(p => p?.Name == n.Item1, null), _fields.FirstOrDefault(f => f?.Name == n.Item1, null))).ToArray();
Name = name;
FullName = fullName;
Rows = rows;
ColumnFlatTypes = ColumnTypes.SelectMany(type => {
var elType = type?.GetElementType();
return type != null && type.IsValueType && type.Name.StartsWith("ValueTuple") ? type.GetFields().Select(f => f.FieldType) :
type != null && elType != null && type.IsArray && elType.IsValueType && elType.Name.StartsWith("ValueTuple") ? elType.GetFields().Select(f => f.FieldType) :
[type];
}).ToList();
ColumnSpans = ColumnTypes.Select(type => {
var elType = type?.GetElementType();
return type != null && type.IsValueType && type.Name.StartsWith("ValueTuple") ? type.GetFields().Length :
type != null && elType != null && type.IsArray && elType.IsValueType && elType.Name.StartsWith("ValueTuple") ? elType.GetFields().Length : 1;
}).ToList();
ColumnWidths = colNames.Select(c => c.Item4).ToList();
ColumnUnits = colNames.Select(c => c.Item3?.Split("|").Select(p => p.Length == 0 ? null : p).ToArray() ?? []).ToList();
}
public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?)>? colNames = null) :
this(name, fullName, rows, colNames?.Select(c => (c.Item1, c.Item2, c.Item3, (int?)null))) {
}
public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?)>? colNames = null) :
this(name, name, rows, colNames) {
}
public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?, int?)>? colNames = null) :
this(name, name, rows, colNames) {
}
public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?, int)>? colNames = null) :
this(name, name, rows, colNames) {
}
public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?, int)>? colNames = null) :
this(name, fullName, rows, colNames?.Select(c => (c.Item1, c.Item2, c.Item3, (int?)c.Item4))) {
}
protected IEnumerable<(string, object?)> GetNamedRowData(T row) {
return _map.Select(i => (i.Item1, i.Item2?.GetValue(row) ?? i.Item3?.GetValue(row)));
}
protected IEnumerable<object?> GetRowData(T row) {
return GetNamedRowData(row).Select(i => i.Item2);
}
public IEnumerable<IEnumerable<object?>> GetData() {
return Rows.Select(GetRowData);
}
public IEnumerable<IEnumerable<(string, object?)>> GetNamedData() {
return Rows.Select(GetNamedRowData);
}
}
}