Welcome to MSDN Blogs Sign in | Join | Help

Mitsu's blog

Discussing topics related to .Net, WPF, C# and Linq
Linq GroupByMany dynamically

Shawn asked me in my last post about GroupByMany how to use it dynamically.

The answer is not easy. So here is a new post to answer to this interesting question.

First you must learn a few things about being dynamic with linq.
There is a very good sample from the C# team (actually we can consider it as a library provided as a sample). ScottGu has post about it here: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx.

One of the power of linq is to be checked at compile-time. You must be aware that using this kind of solution may raise some exceptions at runtime.

Now I have added the Dynamic.cs file to my project and I can use a very useful method: DynamicExpression.ParseLambda.

Here is a new GroupByMany extension method which accepts a list of strings instead of delegates to define all the groupings.
The goal is to call the first GroupByMany method. To do this we have to go from a single string defining the name of a property in the TElement class to a Func<TElement, object>.
We could do this building the expression manually but DynamicExpression.ParseLambda will do it in just a single line.

public static class MyEnumerableExtensions { public static IEnumerable<GroupResult> GroupByMany<TElement>( this IEnumerable<TElement> elements, params string[] groupSelectors) { var selectors = new List<Func<TElement, object>>(groupSelectors.Length); foreach (var selector in groupSelectors) { LambdaExpression l = DynamicExpression.ParseLambda( typeof(TElement), typeof(object), selector); selectors.Add((Func<TElement, object>) l.Compile()); } return elements.GroupByMany(selectors.ToArray()); } ...
Now we can write directly:
DataContext = customers.GroupByMany("Country", "City");

instead of :
DataContext = customers.GroupByMany(c => c.Country, c => c.City);

The full project is attached to this post. (VS2008.)
Posted: Thursday, February 07, 2008 12:04 AM by mitsu
Filed under: , ,

Attachment(s): WPFGroupingTemplateDynamic.zip

Comments

Christopher Steen said:

Sharepoint Two New Tools for SharePoint Development [Via: axshon ] WPF Visio 2007 to XAML Export Add-in...

# February 7, 2008 8:23 AM

Christopher Steen said:

Link Listing - February 6, 2008

# February 7, 2008 8:23 AM

Shawn said:

Wow Mitsu, Thank you so much for your post. I've found both to be very enlightening and informative. As I learn more about LINQ and Lambda expressions,  articles like these really showcase the power behind these new features and what is now possible. Thanks again.

Shawn

# February 7, 2008 10:32 AM

Craig said:

This looks great Mitsu. It may also be possible to create a type-safe dynamic GroupByMany method using a similar technique to that referenced on ScottGu's post about dyanamic linq http://www.albahari.com/nutshell/predicatebuilder.html. I havent tried to implement this approach myself yet, but it seems like it could be useful in avoiding the exceptions that may be raised at runtime by the above technique. Do you think this approach is worth persuing? I may try to implement this if I get some time in the near future!

# February 20, 2008 6:58 AM

mitsu said:

Hi Craig,

My first sample was type-safe: http://blogs.msdn.com/mitsu/archive/2007/12/22/playing-with-linq-grouping-groupbymany.aspx

I was explicitly showing here how to do it dynamically.

The PredicateBuilder is solving something else. It allows you to dynamically compose existing predicates with logical 'or' or 'and'.

It does not help you to build 'p => p.Description' dynamically.

# February 20, 2008 10:25 AM

Is This Thing On? said:

Here are some good resources from Mitsu Furuta to get you started: http://code.msdn.microsoft.com/wpfobjectdumper

# May 2, 2008 8:54 PM

Phiphy said:

Could you help me with this:

if I use the Dynamics libr. I am not able to cast the grouped element back to my original type - List<MyClass>.  

If I use a 'regular' group by (lista.GroupBy(x => new { x.Godina, x.Broizv }) ) I'm able to cast to List<MyClass>.

Could you help me out with this?

var listaGroupByIzvod = lista.GroupByMany("Godina", "Broizv");

var listaGroupByIzvod = lista.GroupBy(x => new { x.Godina, x.Broizv });

foreach (var listaGroup in listaGroupByIzvod)

           {

List<MyClass> tempListaIzvodi = listaGroup.ToList<MyClass>();

           }

# April 29, 2009 6:15 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker