Dynamically build a lambda expression from a collection of objects?

I have a list of views stored in this format:

public class ReportSort { public ListSortDirection SortDirection { get; set; } public string Member { get; set; } } 

And I need to turn it into a lambda expression like Action<DataSourceSortDescriptorFactory<TModel>>

So, suppose I have the following Sorts as reports set:

 new ReportSort(ListSortDirection.Ascending, "LastName"), new ReportSort(ListSortDirection.Ascending, "FirstName"), 

I would need to convert it to such an operator, which will be used as follows:

 .Sort(sort => { sort.Add("LastName").Ascending(); sort.Add("FirstName").Ascending(); }) 

And the signature of the sort method:

 public virtual TDataSourceBuilder Sort(Action<DataSourceSortDescriptorFactory<TModel>> configurator) 

So, I have a method right now:

 public static Action<DataSourceSortDescriptorFactory<TModel>> ToGridSortsFromReportSorts<TModel>(List<ReportSort> sorts) where TModel : class { Action<DataSourceSortDescriptorFactory<TModel>> expression; //stuff I don't know how to do return expression; } 

... and I have no idea what to do here.

EDIT: Answer:

 var expression = new Action<DataSourceSortDescriptorFactory<TModel>>(x => { foreach (var sort in sorts) { if (sort.SortDirection == System.ComponentModel.ListSortDirection.Ascending) { x.Add(sort.Member).Ascending(); } else { x.Add(sort.Member).Descending(); } } }); 

At first I thought that I needed to dynamically build a lambda expression from scratch using the Expression class. Fortunately, this was not so.

+7
c # lambda linq linq-to-objects kendo-ui-mvc
source share
2 answers

... and I have no idea what to do here.

Well, sorry.

What do you have? A List<ReportSort> is called sorts .

What you need? Action<Whatever> .

You have already taken the first step: you have created a method that takes what you have and returns what you need. Great first step.

  Action<DataSourceSortDescriptorFactory<TModel>> expression; //stuff I don't know how to do return expression; 

And you caused that you do not know how to do it. This is a good technique.

Start by filling in what compiles but does not work properly.

 Action<DataSourceSortDescriptorFactory<TModel>> expression = sort => { sort.Add("LastName").Ascending(); sort.Add("FirstName").Ascending(); }; return expression; 

Fine. Now you have a compilation program, which means that you can run your tests and verify that if this case is expected, the test will pass, and if something else is expected, the test will fail.

Now think what I got? I have a list of things and I am doing Action . This means that there is a side effect, possibly involving each item in the list. So there is foreach somewhere:

 Action<DataSourceSortDescriptorFactory<TModel>> expression = sort => { sort.Add("LastName").Ascending(); sort.Add("FirstName").Ascending(); foreach(var sort in sorts) { // Do something } }; return expression; 

Compile it. It fails. Ah, we confuse the sort that we add to the new view that we add. Fix the problem.

 Action<DataSourceSortDescriptorFactory<TModel>> expression = existingSort => { existingSort.Add("LastName").Ascending(); existingSort.Add("FirstName").Ascending(); foreach(var newSort in sorts) { // Do something } }; return expression; 

Great, now we can compile and run the tests again.

The pattern here should be clear. Keep it compiled, continue to run tests, gradually make your program more correct, discussing the actions that you can perform on the values ​​that you have.

Can you finish it?

+5
source share

You can use the following lambda expression, which you can assign to an Action<T> delegate. In this lambda expression, take the variable List<T> and loop over it:

 public static Action<DataSourceSortDescriptorFactory<TModel>> ToGridSortsFromReportSorts<TModel>(List<ReportSort> sorts) where TModel : class { Action<DataSourceSortDescriptorFactory<TModel>> expression = result => { foreach (var sort in sorts) { if (sort.SortDirection == ListSortDirection.Ascending) result.Add(sort.Member).Ascending(); else // or whatever other methods you want to handle here result.Add(sort.Member).Descending(); } }; return expression; } 
+1
source share

All Articles