2012-11-19 129 views
0

我需要按列名称在ajax响应网格中进行排序。列值是以字符串形式存储的编号。如何使用转换构造LambdaExpression

比方说一些琐碎的类(在现实生活中的情况有没有可能修改这个类):

class TestObject 
{ 
    public TestObject(string v) 
    { 
     this.Value = v; 
    } 
    public string Value { get; set; } 
} 

那么简单的测试:

[Test] 
public void LambdaConstructionTest() 
{ 
    var queryable = new List<TestObject> 
        { 
         new TestObject("5"), 
         new TestObject("55"), 
         new TestObject("90"), 
         new TestObject("9"), 
         new TestObject("09"), 
         new TestObject("900"), 
        }.AsQueryable(); 

    var sortingColumn = "Value"; 

    ParameterExpression parameter = Expression.Parameter(queryable.ElementType); 

    MemberExpression property = Expression.Property(parameter, sortingColumn); 
    //// tried this one: var c = Expression.Convert(property, typeof(double)); 

     LambdaExpression lambda = Expression.Lambda(property, parameter); //// constructs: o=>o.Value 

     var callExpression = Expression.Call(typeof (Double), "Parse", null, property); 

     var methodCallExpression = Expression.Call(
      typeof(Queryable), 
      "OrderBy", 
      new[] { queryable.ElementType, property.Type }, 
      queryable.Expression, 
      Expression.Quote(lambda)); // works, but sorts by string values. 
      //Expression.Quote(callExpression)); // getting: System.ArgumentException {"Quoted expression must be a lambda"} 

     var querable = queryable.Provider.CreateQuery<TestObject>(methodCallExpression); 

     // return querable; // <- this is the return of what I need. 
} 

对不起,我不是在清楚我作为@SLaks答案的第一篇文章是正确的,但我不知道如何在这种情况下构造正确的lambda表达式。

终于找到了解决方案这是很好的人谁在列有串,需要通过转换双重价值排序:(用于@SLaks特别感谢他的职务是一个大开眼界):

[Test] 
    public void LambdaConstructionTest2() 
    { 
     // GIVEN 
     var queryable = new List<TestObject> 
          { 
           new TestObject("5"), 
           new TestObject("55"), 
           new TestObject("90"), 
           new TestObject("9"), 
           new TestObject("09"), 
           new TestObject("900"), 
          }.AsQueryable(); 

     var sortingColumn = "Value"; 

     // WHEN 
     ParameterExpression parameter = Expression.Parameter(queryable.ElementType); 

     MemberExpression property = Expression.Property(parameter, sortingColumn); 

     MethodCallExpression callExpression = Expression.Call(typeof (Double), "Parse", null, property); 

     LambdaExpression lambda = Expression.Lambda(callExpression, parameter); // = {Param_0 => Parse(Param_0.Value)} 

     UnaryExpression unaryExpression = Expression.Quote(lambda); // Expression<Func<TestObject,double>> = {Param_0 => Parse(Param_0.Value)} 

     var methodCallExpression = Expression.Call(
      typeof (Queryable), 
      "OrderByDescending", 
      new[] { queryable.ElementType, lambda.ReturnType }, 
      queryable.Expression, 
      unaryExpression); 

     var querable = queryable.Provider.CreateQuery<TestObject>(methodCallExpression); 

     // THEN 
     var expectedMaxValue = queryable.Max(x => Convert.ToDouble(x.Value)); 
     var expectedMinValue = queryable.Min(x => Convert.ToDouble(x.Value)); 

     var list = querable.ToList(); 

     var actualMaxValue = Convert.ToDouble(list.First().Value); 
     var actualMinValue = Convert.ToDouble(list.Last().Value); 
     Assert.AreEqual(expectedMaxValue, actualMaxValue); 
     Assert.AreEqual(expectedMinValue, actualMinValue); 
    } 

回答

2

你可以调用Expression.Call()来创建调用方法的表达式节点。

Expression.Call(typeof(Double), "Parse", null, property) 
+0

感谢您的及时回应,并且是正确的。由于不知道如何从表达式调用构建表达式调用,因此我对表达式树有点不好意思。已编辑我的帖子,在那里披露所有细节。 – nerijus