score:1

Accepted answer
class program
{
    class myentity
    {
        public int id { get; set; }
        public string name { get; set; }

        public myentity(int id, string name)
        {
            id = id; name = name;
        }
    }

    static list<expandoobject> join<tsource, tdest>(list<list<tsource>> items, expression<func<tsource, int>> srcaccessor, expression<func<expandoobject, int>> intermediaryaccessor, expression<func<tsource, tsource, expandoobject>> outerresultselector)
    {
        var joinlambdatype = typeof(expandoobject);            
        expression<func<expandoobject, tsource, expandoobject>> innerresultselector = (expando, item) => expando.addvalue(item);
        
        var joinmethod = typeof(enumerable).getmethods().where(m => m.name == "join").first().makegenericmethod(typeof(tsource), typeof(tsource), typeof(int), joinlambdatype);
        var tolistmethod = typeof(enumerable).getmethods().where(m => m.name == "tolist").first().makegenericmethod(typeof(tdest));


        var joincall = expression.call(joinmethod,
                                expression.constant(items[0]),
                                expression.constant(items[1]),
                                srcaccessor,
                                srcaccessor,
                                outerresultselector);
        joinmethod = typeof(enumerable).getmethods().where(m => m.name == "join").first().makegenericmethod(typeof(tdest), typeof(tsource), typeof(int), joinlambdatype); // from now on we'll be joining expandoobject with myentity
        for (int i = 2; i < items.count; i++) // skip the first two
        {
            joincall =
                expression.call(joinmethod,
                                joincall,
                                expression.constant(items[i]),
                                intermediaryaccessor,
                                srcaccessor,
                                innerresultselector);
        }

        var lambda = expression.lambda<func<list<expandoobject>>>(expression.call(tolistmethod, joincall));
        return lambda.compile()();
    }

    static void main()
    {
        list<list<myentity>> items = new list<list<myentity>> {
            new list<myentity> {new myentity(1,"test1_1"), new myentity(2,"test1_2")},
            new list<myentity> {new myentity(1,"test2_1"), new myentity(2,"test2_2")},
            new list<myentity> {new myentity(1,"test3_1"), new myentity(2,"test3_2")},
            new list<myentity> {new myentity(1,"test4_1"), new myentity(2,"test4_2")}
        };

        expression<func<myentity, myentity, expandoobject>> outerresultselector = (i, j) => new expandoobject().newobject(i, j); // we create a new expandoobject and populate it with first two items we join
        expression<func<expandoobject, int>> intermediaryaccessor = (expando) => ((myentity)((idictionary<string, object>)expando)["i0"]).id; // you could probably get rid of hardcoding this by, say, examining the first key in the dictionary
        
        dynamic cc = join<myentity, expandoobject>(items, i => i.id, intermediaryaccessor, outerresultselector);

        var test1_1 = cc[0].i1;
        var test1_2 = cc[0].i2;

        var test2_1 = cc[1].i1;
        var test2_2 = cc[1].i2;
    }
}

Related Query

More Query from same tag