2012-11-19 67 views
1

我建立這個表達式樹:的NullReferenceException而評估動態構建表達式樹

.Lambda 
#Lambda1<System.Func`2[RTX.Ulysses.TestFramework.TestCaseDataResult, 
System.Collections.Generic.Dictionary`2[System.String,System.Object]]> 
(RTX.Ulysses.TestFramework.TestCaseDataResult $x) 
{ 
.Block(
    System.Collections.Generic.Dictionary`2[System.String,System.Object] $dict, 
    RTX.Ulysses.TestFramework.TestCaseDataResult $x) { 
    .Block(
     System.Collections.Generic.Dictionary`2[System.String,System.Object] $dict, 
     RTX.Ulysses.TestFramework.TestCaseDataResult $x) { 
     $dict = .New 
System.Collections.Generic.Dictionary`2[System.String,System.Object](); 
     .Call $dict.Add(
      "Id", 
      (System.Object)$x.Id) 
    }; 
    $dict 
    } 
} 

有了這個代碼:

_parameterExpression = Expression.Parameter(typeof(TestCaseDataResult), "x"); 
// Init 
     //Expression valExpression = Expression.Property(parameter, "Length"); 
     ParameterExpression dictVar = Expression.Variable(typeof(Dictionary<string, object>), "dict"); 
     Expression newDict = Expression.New(typeof(Dictionary<string, object>).GetConstructors()[0]); 
     Expression builtExpression = Expression.Assign(dictVar, newDict); 

     // Adding a value 
     List<Expression> calls = new List<Expression>(); 
     calls.Add(builtExpression); // Add variable initialization. 
     foreach (var fieldPath in dictionaryToBuild) 
     { 
      Expression valExpression = BuildLambda(fieldPath); 
      calls.Add(Expression.Call(dictVar, typeof (Dictionary<string, object>).GetMethod("Add"), 
             Expression.Constant(fieldPath), 
             Expression.Convert(valExpression, typeof (object)))); 
     } 

     builtExpression = Expression.Block(new List<ParameterExpression>() { dictVar, _parameterExpression }, calls); // dictVar, _parameterExpression 
     builtExpression = Expression.Block(typeof(Dictionary<string, object>), new List<ParameterExpression>() { dictVar, _parameterExpression }, builtExpression, dictVar); 

     Expression<Func<TestCaseDataResult, Dictionary<string, object>>> finalExpression = Expression.Lambda<Func<TestCaseDataResult, Dictionary<string, object>>>(builtExpression, _parameterExpression); 

     return finalExpression; 

public Expression BuildLambda(string expressionString) 
    { 
     Expression builtExpression = _parameterExpression; 
     foreach (var part in expressionString.Split('.')) 
     { 
      builtExpression = Expression.Property(builtExpression, part); 
     } 

     return builtExpression; 
    } 

,但在評價時,我收到NullReferenceException異常。任何人都可以幫忙嗎?

+0

解析堆棧跟蹤,看看那裏的問題。 –

+0

@AlvinWong它沒有說什麼。這裏是它的一部分:在lambda_method(封閉) 在Remotion.Linq.Parsing.ExpressionTreeVisitors.PartialEvaluatingExpressionTreeVisitor.EvaluateSubtree(表達式樹) 在Remotion.Linq.Parsing.ExpressionTreeVisitors.PartialEvaluatingExpressionTreeVisitor.VisitExpression(表達式表達) 在南移。 Linq.Parsing.ExpressionTreeVisitor.VisitLambdaExpression(LambdaExpression表達) 在Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(表達式表達式) 在... – Archeg

回答

1

發現問題。看起來這個表達完美 - 這是評估者的行爲錯誤。我將構建的表達式傳遞給NHibernate,並且它無法從此表達式構建sql。

看來,Dictionary<string, object>() { {"key", "value"}}是不一樣的var dict = new Dictionary<string, object>(); dict.Add("key", "value"); return dict。當我翻譯我的表達式兩個第一個變體 - 工作,現在我能夠構建動態查詢NHibernate。

,我使用到那些有興趣誰一個例子建設者:

// Init 
     NewExpression newDict = Expression.New(typeof(Dictionary<string, object>)); 

     // Adding a value 
     List<ElementInit> elements = new List<ElementInit>(); 

     System.Reflection.MethodInfo addMethod = typeof(Dictionary<string, object>).GetMethod("Add"); 
     foreach (var fieldPath in dictionaryToBuild) 
     { 
      Expression valExpression = BuildLambda(fieldPath); 
      elements.Add(Expression.ElementInit(addMethod, Expression.Constant(fieldPath), Expression.Convert(valExpression, typeof(object)))); 
     } 

     var listInitExpression = Expression.ListInit(newDict, elements); 

     Expression<Func<TestCaseDataResult, Dictionary<string, object>>> finalExpression = Expression.Lambda<Func<TestCaseDataResult, Dictionary<string, object>>>(listInitExpression, _parameterExpression); 

     return finalExpression;