Search code examples
c#.netlambdaexpression-treesfunc

Accessing Type T property in the ParameterExpression type Dictionary<string,T>


I have expression tree code used for data filtering, till date it was used on a Generic list List<T> and following code use to work fine:

var parameterType = Expression.Parameter(typeof(T), "obj");
var memberExpression = Expression.Property(parameterType, "Name");

It was easy to create a binary expression as follows and process the result:

var constantExpression = Expression.Constant("Jack",typeof(string));

var finalExpression = Expression.Equal(memberExpression,constantExpression);

var resultFunc = Expression.Lambda<Func<T, bool>>(finalExpression, parameterType).Compile();

// Final Result
sourceList.Where(obj => resultFunc(obj));

Here Name is a property in Type T, as result post Lambda compilation was Func<T,bool>, I use to apply the same to the Where clause of IEnumerable type. Now the underlying system has changed to use the same code on Dictionary<string,T>, so all the Type T values in the collection now have a string Key associated and type T is now accessible as a value of dictionary object. Also I am applying on a IQueryable, which takes an expression tree the final lambda post compilation at source would be Func<KeyValuePair<string,T>,bool>, therefore cannot apply the Value in the final result processing.

Following is the code modification now:

var parameterType = Expression.Parameter(typeof(KeyValuePair<string,T>), "obj");

Following code fails, since now Name property is in Value of the KeyValuePair and we cannot use it as Type T:

var memberExpression = Expression.Property(parameterType, "Name");

Any pointer to make it work or any suggestion to set me in the right direction?


Solution

  • You could get Expression for calling ["name"] item this way:

    var nameProperty= Expression.Call(parameterType, 
           typeof(IDictionary<string, T>).GetMethod("get_Item"), 
           Expression.Constant("Name")); 
    

    or as:

    var nameProperty = Expression.Property(parameterType, "Item", 
                             new Expression[] { Expression.Constant("Name") });
    

    Both is call of Item property

    EDIT : To get Value from KeyValuePair you have to get property Key, compare it with "Name" and a property Value and compare it with value:

    var parameterType = Expression.Parameter(typeof(KeyValuePair<string,T>), "obj");
    
    var value = Expression.Property(parameterType, "Value" );
    var key = Expression.Property(parameterType, "Key");
    
    var  eq1 = Expression.Equal(key, Expression.Constant("Name"));
    var  eq2 = Expression.Equal(value, constantExpression);
    var and = Expression.And(eq1, eq2);
    var lambda = Expression.Lambda(and, parameterType);