Я сделал нечто подобное. Анонимные типы не работали, так как мне приходилось делать столбцы динамически, и анонимные типы все еще должны быть известны во время компиляции. Тем не менее, ExpandoObject
позволяет определить свойства во время выполнения.
Я сделал быстрое консольное приложение в качестве доказательства:
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
List<Record> input = new List<Record>();
input.Add(new Record { CheckNumber = 100, Step = "Book", Amount = 100 });
input.Add(new Record { CheckNumber = 100, Step = "Bank", Amount = 100 });
input.Add(new Record { CheckNumber = 100, Step = "Account", Amount = 100 });
input.Add(new Record { CheckNumber = 101, Step = "Book", Amount = 75 });
input.Add(new Record { CheckNumber = 101, Step = "Bank", Amount = 75 });
List<ExpandoObject> results = GetPivotRows(input);
//test
for (int i = 0; i < results.Count; i++)
{
dynamic record = results[i];
Console.WriteLine("{0} - {1} - {2} - {3}", record.CheckNumber, record.Book, record.Bank, record.Account);
}
}
public static List<ExpandoObject> GetPivotRows(List<Record> input)
{
List<string> steps = input.Select(e => e.Step).Distinct().ToList();
Dictionary<int, ExpandoObject> outputMap = new Dictionary<int,ExpandoObject>();
for (int i = 0; i < input.Count; i++)
{
dynamic row;
if(outputMap.ContainsKey(input[i].CheckNumber))
{
row = outputMap[input[i].CheckNumber];
}
else
{
row = new ExpandoObject();
row.CheckNumber = input[i].CheckNumber;
outputMap.Add(input[i].CheckNumber, row);
// Here we're initializing all the possible "Step" columns
for (int j = 0; j < steps.Count; j++)
{
(row as IDictionary<string, object>)[steps[j]] = new Nullable<int>();
}
}
(row as IDictionary<string, object>)[input[i].Step] = input[i].Amount;
}
return outputMap.Values.OrderBy(e => ((dynamic)e).CheckNumber).ToList();
}
}
public class Record
{
public int CheckNumber { get; set; }
public string Step { get; set; }
public decimal Amount { get; set; }
}
Выход:
100 - 100 - 100- 100
101 - 75 - 75 -
Вы можете использовать отражение для проверки фактических свойств, созданных в процессе.
EDIT: Прояснение это немного - если я изменю, что «тест» петля в основном для:
for (int i = 0; i < results.Count; i++)
{
Console.WriteLine(string.Join(" - ", results[i]));
}
я получаю:
[CheckNumber, 100] - [Book, 100] - [Bank, 100] - [Account, 100]
[CheckNumber, 101] - [Book, 75] - [Bank, 75] - [Account, ]
ExpandoObject
орудия IDictionary<string, object>
за кулисами, чтобы сохранить все, что ему нужно, но в то же время реализует IDynamicMetaObjectProvider
и работает с динамической привязкой.
Вы хотите, чтобы вы динамически генерировали свойства анонимного типа, исходя из значений времени выполнения? Нет, это не сработает. Вы можете использовать ExpandoObject, потенциально ... –
Начальные значения уже находятся в списке LINQ. Мне нужно преобразовать его с помощью стержня. Я знаю, что свойство STEP есть, я просто не знаю, сколько есть и нужно создать X количество столбцов на основе шагов –
Мне нужно было сделать что-то подобное. [ExpandoObject] (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject (v = vs.110) .aspx), как уже упоминалось, это единственный способ сделать это. – McAden