Replace parameter value in expression tree

After a long search, I still cannot find the answer I'm looking for. I found answers about adding and removing parameters from the tree, but not about replacing certain parameters.

My first method works the way I would like, I need to replace the partitionKey value with a shielded Uri value, and then return the results without escaping.

public override IList<T> GetRowEntityList(string partitionKey) { IList<T> rowEntities = base.GetRowEntityList(Uri.EscapeDataString(partitionKey)); return rowEntities.Select(UnEscapeRowEntity).ToList(); } 

The problem I am facing redefines this method to behave the same. I already know that type T has the PartitionKey and RowKey , but can also have any other number of properties.

For an example predicate:

 x => x.RowKey == "foo/bar" && x.SomeValue == "test" 

I expect him to become

 x => x.RowKey == Uri.EscapeDataString("foo/bar") && x.SomeValue == "test" 

Is there any way to do this?

My base class uses this predicate to find a table in a table containing objects of type T using the Where(predicate) call

 public override IList<T> GetRowEntityList(System.Linq.Expressions.Expression<Func<T, bool>> predicate) { //modify predicate value here return base.GetRowEntityList(predicate); } 
+4
source share
1 answer

You need to implement ExpressionVisitor :

 class MyVisitor : ExpressionVisitor { protected override Expression VisitBinary(BinaryExpression node) { if(CheckForMatch(node.Left)) return Expression.Equal(node.Left, Rewrite(node.Right)); if(CheckForMatch(node.Right)) return Expression.Equal(Rewrite(node.Left), node.Right); return Expression.MakeBinary(node.NodeType, Visit(node.Left), Visit(node.Right)); } private bool CheckForMatch(Expression e) { MemberExpression me = e as MemberExpression; if(me == null) return false; if(me.Member.Name == "RowKey" || me.Member.Name == "PartitionKey") return true; else return false; } private Expression Rewrite(Expression e) { MethodInfo mi = typeof(Uri).GetMethod("EscapeDataString"); return Expression.Call(mi, e); } } 

I think that's right. This is a little hard to verify. Please note that this will only work for a limited case (x => x.RowKey == "some string") . This will not work for (x => x.RowKey.Equals("somestring") . It will also not work for (x => x.RowKey() == "some string") .

Then you use the embedded visitor to re-record the predicate:

 Expression<Func<T, bool>> predicate = (s => s.RowKey == "1 2"); ExpressionVisitor v = new MyVisitor(); Expression<Func<T, bool>> rewrittenPredicate = v.Visit(predicate); //rewrittenPredicate then tests if s.RowKey == "1%202" 
+2
source

All Articles