Você pode pré-cache os nomes das propriedades em que você está interessado (ou seja, aqueles com o atributo de descrição) e, em seguida, usá-los para pegar apenas os valores em que você está interessado.
Eu invadi um exemplo rápido disso, não é o código mais robusto, mas mostra a ideia geral (faz muitas suposições sobre o pedido) e apenas buscou os atributos uma vez.
(Editar: percebi que precisávamos apenas chamar GetProperties uma vez para tudo).
var whitelist = typeof (DocumentTrackerChaseReport)
.GetProperties()
.Where(x => Attribute.IsDefined(x, typeof (DescriptionAttribute)));
var rows = things.Select(x => whitelist.Select(y => y.GetValue(x) ?? ""));
Isso lhe dará um IEnumerable<IEnumerable<object>>
, ou em outras palavras, uma lista de linhas e para cada linha, uma lista de colunas (com o valor de cada coluna sendo um objeto).
Você pode então iterar com isso da seguinte maneira (código pseudo)
foreach (var header in whitelist) {
// print column of header row
}
foreach (var row in rows) {
foreach (var col in row) {
// print an individual cell
}
// break for a new row
}