Search code examples
c#asp.netlinqprojection

linq group by with projection to class with non-parameterless constructor


I'm having trouble doing a group by linq statement that projects into a list of Foo in which each Foo can also contain a list of Bar. In my case, neither of the classes have parameterless constructors, so I'm getting a little lost in the syntax.

https://dotnetfiddle.net/9zplqa

public class linqGrouping
{

    public linqGrouping()
    {
        var data = this
            .TestData()
            .GroupBy(gb => new { gb.GroupProperty, gb.RandomProperty })
            .Select(s => new Foo(
                s.Key.GroupProperty, 
                s.Key.RandomProperty, 
                // Here's where I'm having issues, I was the non key parts of the group to be placed into a list of bar, I'm not sure how to access the "Values" as opposed to the Key
                new List<Bar>()
                {
                         // vvv Here's my problem area vvv //
                    //new Bar(someProperty, someOtherProperty)
                         // ^^^ Here's my problem area ^^^ //
                }
            ));

        // The Expected object I'm hoping to create would be:
        List<Foo> foo = new List<Foo>()
        {
            new Foo(1, 1, new List<Bar>()
                    {
                        new Bar(1, "test"),
                        new Bar(2, "test2")
                    }),
            new Foo(2, 1, new List<Bar>()
                    {
                        new Bar(1, "test")
                    })
        };
    }

    public List<RawData> TestData()
    {
        List<RawData> data = new List<RawData>();

        data.Add(new RawData()
                 {
                     GroupProperty = 1,
                     RandomProperty = 1,
                     SomeOtherProperty = "test",
                     SomeProperty = 1
                 });

        data.Add(new RawData()
                 {
                     GroupProperty = 1,
                     RandomProperty = 1,
                     SomeOtherProperty = "test2",
                     SomeProperty = 2
                 });

        data.Add(new RawData()
                 {
                     GroupProperty = 2,
                     RandomProperty = 1,
                     SomeOtherProperty = "test",
                     SomeProperty = 1
                 });

        return data;
    }

}

public class RawData
{
    public int GroupProperty { get; set; }
    public int RandomProperty { get; set; }
    public int SomeProperty { get; set; }
    public string SomeOtherProperty { get; set; }
}

public class Foo
{
    public int GroupProperty { get; private set; }
    public int RandomProperty { get; private set; }
    public List<Bar> Bars { get; private set; }

    public Foo(int groupProperty, int randomProperty, List<Bar> bars)
    {
        this.GroupProperty = groupProperty;
        this.RandomProperty = randomProperty;
        this.Bars = bars;
    }
}

public class Bar
{
    public int SomeProperty { get; private set; }
    public string SomeOtherProperty { get; private set; }

    public Bar(int someProperty, string someOtherProperty)
    {
        this.SomeProperty = someProperty;
        this.SomeOtherProperty = someOtherProperty;
    }
}

How do I go about doing this? Is there a better way to go about it than the direction I'm going in?


Solution

  • To select the two other properties from the grouping into a collection of Bar, you can simply do:

    var data = this.TestData()
        .GroupBy(gb => new { gb.GroupProperty, gb.RandomProperty })
        .Select(s => new Foo(
             s.Key.GroupProperty, 
             s.Key.RandomProperty, 
             s.Select(b => new Bar(b.SomeProperty, b.someOtherProperty)).ToList())
            ));