Building Dynamic GroupBy Selector Expression Tree With Multiple Properties

c# expression expression-trees group-by linq

Question

I am to build a dynamic Expression Tree for GroupBy. All i want to achieve is like this.

var NestedGrouped = listOfPerson.GroupByMany(x => x.Name,x=>x.Age).ToList(); 

My Person Class is like :-

class Person
{
 public string Name{ get; set; }
 public int Age{ get; set; }
 public float Salary{ get; set; }
}
public class GroupResult
{
        public object Key { get; set; }
        public int Count { get; set; }
        public IEnumerable Items { get; set; }
        public IEnumerable<GroupResult> SubGroups { get; set; }
        public override string ToString()
        { return string.Format("{0} ({1})", Key, Count); }
 }
 public static class MyEnumerableExtensions
 {
        public static IEnumerable<GroupResult> GroupByMany<TElement>(
            this IEnumerable<TElement> elements,
            params Func<TElement, object>[] groupSelectors)
        {
            if (groupSelectors.Length > 0)
            {
                var selector = groupSelectors.First();

                //reduce the list recursively until zero
                var nextSelectors = groupSelectors.Skip(1).ToArray();
                return
                    elements.GroupBy(selector).Select(
                        g => new GroupResult
                        {
                            Key = g.Key,
                            Count = g.Count(),
                            Items = g,
                            SubGroups = g.GroupByMany(nextSelectors)
                        });
            }
            else
                return null;
        }
    }

For Single Property I am able to build the expression but i want to do GROUPBY with multiple columns as shown above. FOR SINGLE PROPERTY :-

 ParameterExpression parameter = Expression.Parameter(typeof(Person), "lambdaKey");
            var menuProperty = Expression.PropertyOrField(parameter, "Name");
            var lambda = Expression.Lambda<Func<Person, string>>(menuProperty, parameter);
            var selector = lambda.Compile();
            var result = P1.GroupByMany(selector);// P1 is list of PERSON

How to ADD multiple columns in Expression Tree (e.g (x => x.Name,x=>x.Age)).
Please Help. Thanks in Advance.

Popular Answer

GroupByMany() accepts array of delegates, one delegate for each key. So, what you need is to create and compile a separate expression for each key.

The code could look something like:

private static Func<TElement, object> CreateSelector<TElement>(string key)
{
    var parameter = Expression.Parameter(typeof(TElement), "lambdaKey");
    var property = Expression.PropertyOrField(parameter, key);
    var lambda = Expression.Lambda<Func<TElement, string>>(property, parameter);
    return lambda.Compile();
}

public static IEnumerable<GroupResult> GroupByMany<TElement>(
    this IEnumerable<TElement> elements,
    params string[] groupKeys)
{
    return elements.GroupByMany(groupKeys.Select(CreateSelector<TElement>).ToArray());
}


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why