Как я могу использовать Linq для проецирования этой родительской и дочерней объектной модели в один плоский объект? - PullRequest
7 голосов
/ 08 сентября 2011

Я пытаюсь сгладить простой класс с массивом родительский + дочерний в один класс.*

Ответы [ 2 ]

12 голосов
/ 08 сентября 2011

Чистый подход Linq

Вы можете использовать перегрузку SelectMany(), которая позволяет вам указать селектор результата, который вызывается для каждого элемента в коллекции:

Проецирует каждый элемент последовательности в IEnumerable, выравнивает результирующие последовательности в одну последовательность, и вызывает селектор результата функция на каждом элементе в нем.

List<Foo> foos = new List<Foo>();
var fooProjections = foos.SelectMany(x => x.PewPews, (foo, pew) => new FooProjection() 
{ 
    Id = foo.Id, 
    Name = foo.Name,
    PewPewName = pew.Name,
    PewPewWhatever = pew.Whatever 
}).ToList();

Этот подход является наиболее кратким, но требует некоторого времени для привыкания, особенно если вы не много работали с Linq.

Edit:

Согласно комментарию @ AS-CII, было бы более легко понять (и это важно для поддержания базы кода) просто использовать цикл и простую проекцию с Select(). Если у кого-то есть проблемы с Linq в этом сценарии, два вложенных цикла тоже подойдут. Я покажу оба для полноты.

Использование цикла foreach и проекции Select

Просто переберите все Foos и создайте новый FooProjection для каждого PewPew в текущем элементе. Добавьте их все в список fooProjections, который находится в области видимости. Этот подход использует проекцию Linq для отображения из каждого PewPew в FooProjection, используя foo из цикла foreach.

List<Foo> foos = new List<Foo>();
List<FooProjection> fooProjections = new List<FooProjection>();

foreach(var foo in foos)
{
    var someFooProjections = foo.PewPews.Select(x => new FooProjection() 
    { 
        Id = foo.Id, 
        Name = foo.Name, 
        PewPewName = x.Name, 
        PewPewWhatever = x.Whatever 
    });
    fooProjections.AddRange(someFooProjections);
}

Использование двух вложенных циклов foreach

Просто используйте два цикла foreach, внешнюю итерацию по Foos, внутреннюю по коллекции PewPews в текущем foo - добавьте новый FooProjection в список fooProjections, который находится в области видимости. Этот подход вообще не использует Linq.

List<FooProjection> fooProjections = new List<FooProjection>();
foreach (var foo in foos)
    foreach (var pew in foo.PewPews)
    {
        fooProjections.Add(new FooProjection()
        {
            Id = foo.Id,
            Name = foo.Name,
            PewPewName = pew.Name,
            PewPewWhatever = pew.Whatever
        });
    }
6 голосов
/ 08 сентября 2011

Я считаю, что выражения запроса с несколькими from гораздо проще написать, чем вызовы SelectMany. Они компилируются в одно и то же.

List<Foo> foos = GetFoos();

var projected = 
    from foo in foos
    from pewPew in foo.PewPews
    select new FooProjection
        { Id = foo.Id, 
          Name = foo.Name, 
          PewPewName = pewPew.Name, 
          PewPewWhatever = pewPew.Whatever };
...