roboris
roboris

Reputation: 352

C# MemberExpression for a specific dictionary item

I am trying to dynamically generate binary expressions using Expression.MakeBinary:

public static BinaryExpression MakeBinary(
    ExpressionType binaryType,
    Expression left,
    Expression right
)

A simple example of that for Property "Bar" of class "Foo" would be:

var param = Expression.Parameter(typeof(Foo));
var left = MemberExpression.Property(param, "Bar");
var propertyType = typeof(Foo).GetProperty("Bar").PropertyType;
var right = Expression.Constant(Convert.ChangeType("newValue", propertyType ));
var expression = Expression.MakeBinary(ExpressionType.Equal, left, right);

My goal is to be able to do the same thing as above, but instead of comparing "Bar" property with "newValue", in my case "Bar" is a dictionary and I want to compare a specific entry of that dictionary with "newValue". What I want to achieve would look like this (but this code is not valid):

var param = Expression.Parameter(typeof(Foo));
var left = MemberExpression.Property(param, "Bar[\"entryName\"]");

I would suppose what I am trying to do is possible, but I can't seem to find the right syntax/class/method to use. Obviously the code above returns an error, since Bar["entryName"] is not a property. But how can I build the expression based on a specific entry in a dictionary for a given Type?

The high level application of this is to be able to apply rules, using field/operator/compareValue as parameters, but being able to indicate the "path" to that field (depending on the class, sometimes it would be a plain property, or as asked here, an entry in a dictionary, etc.).

Thank you

Upvotes: 4

Views: 1033

Answers (1)

René Vogt
René Vogt

Reputation: 43916

You can use Expression.MakeIndex():

var param = Expression.Parameter(typeof(Foo));
var bar = MemberExpression.Property(param, "Bar");

Type dictionaryType = typeof(Foo).GetProperty("Bar").PropertyType;
PropertyInfo indexerProp = dictionaryType.GetProperty("Item");
var dictKeyConstant = Expression.Constant("entryName");
var dictAccess = Expression.MakeIndex(bar, indexerProp, new[] {dictKeyConstant});

var propertyType = indexerProp.PropertyType;
var right = Expression.Constant(Convert.ChangeType("newValue", propertyType ));
var expression = Expression.MakeBinary(ExpressionType.Equal, dictAccess, right);    

The property name of an indexer is always "Item". The dictKeyConstant should be the expression for your dictionary's key.

Upvotes: 4

Related Questions