2013-04-09 46 views
4

經過很長一段時間的搜索後,我仍然沒有找到我正在尋找的答案。我找到了有關從樹中添加和刪除參數的答案,但沒有任何關於替換特定參數的答案。替換表達式樹中的參數值

我的第一個方法是按照我希望的方式工作,我需要用Uri轉義值替換partitionKey值,然後返回未轉義的結果。

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

我遇到的問題是重寫此方法的行爲方式相同。我已經知道類型T具有屬性PartitionKeyRowKey,但也可以具有任何其他數量的屬性。

對於樣品斷言:

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

我希望它成爲

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

有沒有辦法做到這一點?

我的基類中使用這個謂詞做就使用Where(predicate)呼叫

public override IList<T> GetRowEntityList(System.Linq.Expressions.Expression<Func<T, bool>> predicate) 
{ 
    //modify predicate value here 

    return base.GetRowEntityList(predicate); 
} 
+0

您是否正在尋找一種方法來檢測與'x.RowKey'在謂語一些字符串進行比較,然後返回一個新的謂詞與此相同,只是使用轉義字符串? – Shlomo 2013-04-09 17:40:32

+0

你問如何構建表達式,以便用戶只需要提供一個簡單的字符串? – Justin 2013-04-09 17:40:45

+0

@Shlomo是的。我正在尋找檢測與x.RowKey或x.PartitionKey的比較,並轉義這些字符串,同時保持表達式的其餘部分不變。 – jzworkman 2013-04-09 17:42:20

回答

2

T型的實體,您需要實現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); 
    } 
} 

我想那就對了。這有點難以測試。請注意,這隻適用於(x => x.RowKey == "some string")這種有限的情況。它不適用於(x => x.RowKey.Equals("somestring")。它也不適用於(x => x.RowKey() == "some string")

您再使用實施訪問者重新寫謂詞:

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" 
+0

這是我採取的方法,當我在這裏看到您的答案時,我實際上剛寫完了我正在使用的訪問者。 – jzworkman 2013-04-09 19:59:41

+1

恩,謝謝我有機會把這些東西甩掉。 :) – Shlomo 2013-04-09 20:09:40