1

I have a scenario where I dynamically create a WHERE clause from a client-side grid's configuration. The client sends some json to the server which I then parse and subsequently convert into an expression so it can be passed into the repository as a where clause.

For the moment I'm struggling with creating expressions for complex property types, like this one:

public partial class Resource
{
  public string DisplayName { get; set; }
  public virtual ResourceType ResourceType { get; set; }
}

The code below that does the translation to an expression works well for simple types like the Displayname property. The expression will be something like:

x => x.DisplayName == "ValueEnteredByUserInTheUI"

However, when a value is entered in the grid for the ResourceType property, the expression will ultimately be something like:

x => x.ResourceType == "ValueEnteredByUserInTheUI"

I'm missing one step to convert into this:

 x => x.ResourceType.Name == "ValueEnteredByuserInTheUI"

Anyone can point me in the right direction here?

public Expression<Func<T, bool>> GetExpression<TEntity>(string field, string operation, object value, string ignoreCase)
{
 Expression<Func<T, bool>> whereClause = default(Expression<Func<T, bool>>);

// Define lambda
ParameterExpression param = Expression.Parameter(typeof(T), "x");    
 MemberExpression member = Expression.Property(param, field);

 // Get property type
  Type propertyType = member.Type;

  // Get converter for type
   TypeConverter converter = TypeDescriptor.GetConverter(propertyType);

   // Convert property to type
   var result = converter.ConvertFrom(value.ToString());

   // Convert value to constant value
   ConstantExpression constant = Expression.Constant(result);

    Expression comparingExpression = default(BinaryExpression);
    switch (operation)
    {
      case "like":
           comparingExpression = Expression.Equal(member, Expression.Convert(constant, member.Type));
           break;           
       default:
           break;
   }

  var lambda = Expression.Lambda<Func<T, bool>>(comparingExpression, param);
   whereClause = whereClause == default(Expression<Func<T, bool>>) ? lambda : NewPredicateBuilder.And(whereClause, lambda);
        return whereClause;
  }
hbulens
  • 1,872
  • 3
  • 24
  • 45

1 Answers1

6

Apparently not a lot of people are keen on expressions. Anyway, I have created a workaround for this issue. I added another parameter in the method indicating the property name of the complex property of the root object.

 // Get property of root object
 MemberExpression member = Expression.Property(param, field);

 // Get property of property
 MemberExpression memberField = Expression.PropertyOrField(member, complexProperty);

It's not very scalable nor generic but this will do it for now.

hbulens
  • 1,872
  • 3
  • 24
  • 45
  • What do you pass as the complexProperty? Basically could you provide both in your answer? Have you found an aswwer if you wanted to go deeper? Thanks. – panoskarajohn May 15 '20 at 13:31
  • It would be a dot-separated string of your class' graph navigation such as "ResourceType.Name" where "ResourceType" is a class with a "Name" property. Not sure what you mean by going deeper. Not too long ago, I uploaded a little project on GitHub: https://github.com/dimenics/dime-expressions. Take a look and see if this works for you. – hbulens May 17 '20 at 08:14
  • Hello hbulens. Thanks for the response.I will definetely take a look to your link. Your answer works greatly and i managed to solve my issue. Just to clarify. What I mean by going deeper...Imagine having a class like your resource class. 'Resource.ResourceType.ResourceCode.Name', meaning Resource code was another object and a property to your ResourceType. How would you go accessing the ResourceCode.Name property? – panoskarajohn May 17 '20 at 08:27