2

I'm trying to dynamically generate a model property in my Lambda express. In my controller I have the following method:

public ActionResult FilterSubCategory(string filter, string selected)
{
    IList<Item> model = db.Items.Where(p => p.Make == selected).ToList();
    var viewModel = Mapper.Map<IList<ItemViewModel>>(model);
    return View("~/Views/Phone/Index.cshtml", viewModel);
}

I want to use this method to filter my page's column so I'm passing the filter(model property to filter) and the actual selected property value.

I want to replace the 'Make' ('hardcoded' here) here with the value of the filter string passed. Is there a way to do this?

Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
Orphu.of.io
  • 125
  • 1
  • 16
  • Have you considered usage of [Dynamic LINQ](http://dynamiclinq.codeplex.com/)? – Konrad Kokosa Apr 11 '14 at 14:25
  • 1
    possible duplicate of [How do i create the following LINQ expression dynamically?](http://stackoverflow.com/questions/22916231/how-do-i-create-the-following-linq-expression-dynamically) – Servy Apr 11 '14 at 14:26
  • @Servy Thank you for the link. That solution worked wonderfully. Sorry for the duplicate! Upvoted here and in Original thread. – Orphu.of.io Apr 11 '14 at 15:26

1 Answers1

1

This is what I do:

public static Expression<Func<TModel, TProperty>> GenerateModelExpression<TModel, TProperty>(PropertyInfo property)
{
     ParameterExpression fieldName = Expression.Parameter(typeof(TModel), "m");

     var propertyExpr = Expression.Property(itemExpr, property.Name);

     return Expression.Lambda<Func<TModel, TProperty>>(propertyExpr, fieldName);
}

The property parameter would be 'Make' in your case which you can get using reflection.

https://github.com/AmmarCSE/razor-grid

Edit

After reviewing the question more precisely and referencing former answery by @Servy, How do i create the following LINQ expression dynamically?, here is a solution:

public static Expression<Func<TModel, TProperty>> GenerateModelExpression<TModel, TProperty>(string filter, string select)
{
     ParameterExpression param = Expression.Parameter(typeof(TModel), "m");
     var body = Expression.Equal(Expression.Property(param, typeof(TModel).GetProperty(filter))
      , Expression.Constant(select));

     return Expression.Lambda<Func<TModel, TProperty>>(body, param);
}
Community
  • 1
  • 1
AmmarCSE
  • 30,079
  • 5
  • 45
  • 53
  • This is effectively a custom `Select`, and doesn't compare that property value to the value to filter on. – Servy Apr 11 '14 at 14:42
  • Hey @Servy, I thought the user was asking how to dynamically construct the lambda expression itself? – AmmarCSE Apr 11 '14 at 14:43
  • He's asking how to filter a query where a property (determined by its string name) is equal to a string value. This doesn't do that. – Servy Apr 11 '14 at 14:44
  • @Servy, you are right and I overlooked that. How about something like typeof(TModel).GetProperty(filter)? – AmmarCSE Apr 11 '14 at 15:10
  • I fail to see how that code would solve this problem. – Servy Apr 11 '14 at 15:14
  • @Servy, with my code above, he can pass a string and then use typeof(TModel).GetProperty(param) to generate his expression. Afterall, the questioner said "I want to replace the 'Make' ('hardcoded' here) here with the value of the filter string passed. Is there a way to do this?" – AmmarCSE Apr 11 '14 at 15:17
  • Yes, there most certainly are ways to do this, you just aren't doing them. You're getting the property value dynamically *but you're not using it*. He needs to use it to compare its value with a known string value. You have skipped that step. This is just half of the solution. – Servy Apr 11 '14 at 15:19