Создайте последовательность анонимных типов из строк в DataTable - PullRequest
5 голосов
/ 16 июня 2011

Это упражнение «посмотрим, можно ли это сделать» больше всего на свете.

Предположим, у меня есть DataTable с несколькими столбцами.Используя linq, можно ли выбрать строки таблицы так, чтобы результатом была последовательность анонимного типа, где каждое свойство анонимного типа названо в соответствии с именем столбца DataTable, а тип каждого свойства установленсоответственно.

Итак, если мой DataTable имеет три столбца, например, так:

Name = "Column1",  DataType = string
Name = "Column2",  DataType = integer
Name = "Column3",  DataType = bool

Затем я хочу выбрать все строки в DataTable так, чтобы у анонимного типа было три свойства:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => **** MAGIC HERE ****)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

Я знаю, что могу сделать это:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => 
   new 
   {
       Column1 = r.Field<string>("Column1"),
       Column2 = r.Field<int>("Column2"),
       Column3 = r.Field<bool>("Column3"),
   }
)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

, но это требует жесткого кодирования имен свойств в новом предложении, тогда как я хотел бы, чтобы имена свойств происходили из коллекции ColumnsDataTable.

Я надеюсь, что объяснил это достаточно ясно.Поэкспериментировав с этим немного, я начинаю думать, что все, что я придумаю, будет большим беспорядком с точки зрения читабельности и удобства сопровождения, но я подумал, что я спрошу.

Ответы [ 2 ]

3 голосов
/ 16 июня 2011

Боюсь, что нет такой магии (по крайней мере, с анонимными типами). Анонимные типы - это неявные типы, сгенерированные компилятором как неизменяемые классы с их свойствами, названными и типизированными явной операцией присваивания, как во втором примере (во время компиляции).

То, что вы хотите сделать, потребует динамического типа, созданного во время выполнения.

2 голосов
/ 20 февраля 2014

Как уже установлено в ответе Брэндона, этого нельзя сделать с анонимными типами, так как они генерируются во время компиляции. Однако, как уже упоминалось, вы можете использовать динамику для получения аналогичного синтаксиса.

Например, вы можете получить следующий синтаксис (на основе вашего примера):

var seq = table.AsEnumerable().Select(row => (dynamic)new DynamicDataRow(row));
foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

Использование простой динамической оболочки для ваших DataRows:

class DynamicDataRow : DynamicObject
{
    private readonly DataRow row;

    public DynamicDataRow(DataRow row)
    {
        this.row = row;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        DataColumn column = row.Table.Columns[binder.Name];
        if (column != null)
        {
            result = row[column];
            return true;
        }

        result = null;
        return false;
    }
}

Я не совсем уверен, каков ваш вариант использования, но, надеюсь, это поможет вам в правильном направлении, если вы решите, что динамика является приемлемой заменой для анонимных типов.

...