Open blakepell opened 4 years ago
I think some sort of extension would be pretty useful, but I don't think needs to be aware of those types. My first thought was implementing an interface, and wrapping your IDataReader.
@blakepell There will not be any built-in knowledge of IDataReader or similar, but I will add some convenience methods to render POCO-objects as tables.
Using AnsiConsole
directly is mostly for convenience and small apps. I recommend that you pass an IAnsiConsole
around for more complex applications. This way, it's easier to unit test the functionality of your application. You can get the IAnsiConsole
for AnsiConsole
via AnsiConsole.Console
property.
Here's a quick experiment I did for adding rows from a collection of POCO objects:
/// <summary>
/// Adds multiple rows to the table.
/// </summary>
/// <typeparam name="T">The item type.</typeparam>
/// <param name="table">The table to add the row to.</param>
/// <param name="values">The values to create rows from.</param>
/// <param name="columnFunc">A collection of functions that gets a column value.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Table AddRows<T>(this Table table, IEnumerable<T> values, params Func<T, object>[] columnFunc)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
if (values is null)
{
throw new ArgumentNullException(nameof(values));
}
foreach (var value in values)
{
var columns = new List<IRenderable>();
foreach (var converter in columnFunc)
{
var column = converter(value);
if (column == null)
{
columns.Add(Text.Empty);
}
else if (column is IRenderable renderable)
{
columns.Add(renderable);
}
else
{
var text = column?.ToString() ?? string.Empty;
if (string.IsNullOrWhiteSpace(text))
{
columns.Add(Text.Empty);
}
else
{
columns.Add(new Markup(text));
}
}
}
table.AddRow(columns.ToArray());
}
return table;
}
Usage:
var table = new Table()
.AddRows(
movies,
m => $"[red]{m.Name}[/]",
m => $"[green]{m.BoxOffice:C}[/]",
m =>
{
if (m.BoxOffice > 2000000000)
{
return new Panel("[green]😱[/]").BorderStyle("yellow");
}
return "[red]Lame[/]";
});
@patriksvensson @blakepell, I wrote a library for Dumping
any .NET object in a structured, colorful way. It uses Tables from Spectre.Console.
It is highly configurable and it supports max depth, circular references, type name formatting and more.
It is called Dumpify
https://github.com/MoaidHathot/Dumpify/
You can dump to Console, Debug, Trace or any custom TextWriter you want (using AnsiConsole behind the scenes). Some examples:
var moaid = new Person { FirstName = "Moaid", LastName = "Hathot" };
var haneeni = new Person { FirstName = "Haneeni", LastName = "Shibli" };
moaid.Spouse = haneeni;
haneeni.Spouse = moaid;
moaid.Dump();
@MoaidHathot Beautiful!
I don't know if there was a way to do this already built in, but I end up working with lots of data whether it's in a
IDataReader
,IEnumerable<T>
orIEnumerable<dynamic>
(from Dapper which I use frequently, I had to do some acrobatics to reflect on the dynamic IEnumerable but it's working out well). If this didn't exist I didn't know if something like this would be useful. I'm using this for a hobby project so I haven't thought it through API wise or refactored anything but below is a brief example of how I'm using it (apologies if the inlined SQL makes anyone cringe, it's for illustration):In this example
Terminal
is just anIAnsiConsole
with the additional rendering functions bolted on. I wanted to write extension methods toAnsiConsole
but the static class prohibited that (and I couldn't use the partial class pattern being outside of the Spectre.Console assembly.I didn't know if anyone else would use this kind of functionality or find it desirable but I thought I'd ask. Love the project also, thank you for sharing it!
Please upvote :+1: this issue if you are interested in it.