2013-08-19 33 views
16

我有一个名为sortColumn的变量,它包含我想对查询结果排序的列的文本。我也有一个通用存储库,它将包含我想要排序的字段的表达式作为参数。我似乎无法从字符串属性名称获取到表达式。从字符串属性名称创建通用表达式

所以一般的仓库,我有包含以下方法

public IEnumerable<TEntity> Get<TOrderBy>(Expression<Func<TEntity, bool>> criteria, 
              Expression<Func<TEntity, TOrderBy>> orderBy, int pageIndex, 
              int pageSize, 
              bool isAssendingOrder = true, 
              EnumDeletePolicy deletePolicy = EnumDeletePolicy.ExcludeDeleted) 

通知本拿到第二个参数是表达-Func键-TEntity,TOrderBy。正如我所提到的,我有一个名为sortColumn的变量,它包含我的TEntity对象上属性的字符串,我需要将此字符串转换为可传递给Get方法的Expression。

这是我现在所拥有的。

 var parameter = Expression.Parameter(typeof(IContract)); 
     var memberExpression = Expression.Property(parameter, data.SortColumn); 
     var lambdaExpression = Expression.Lambda(memberExpression, parameter); 

它创建一个LambdaExpression类型的对象。此LambdaExpression的实际类型是Expression-Func-IContract,字符串(或属性的任何sortColumn类型)。如果我调用Get方法并传入此LambdaExpression并将其显​​式转换为Expression类型,那么它将正常工作。问题是我不知道表达式类型是什么,它可能是一个字符串,int,int ?,等等。这一切都取决于sortColumn属性中特定属性的类型。

你能帮我把这最后一跳跳到正确的表情类型吗?

根据Marc的建议编辑: 我几乎有这个工作,实际上是专门针对它正在工作的问题,但我剩下1个问题。

我正在查询的实体类型IContract实际上是从IRelationship继承的。如果我从IContract接口指定一个字段,那么上面的代码就可以工作。如果我从IRelationship接口指定一个字段,那么下面的行会失败。

 var memberExpression = Expression.Property(parameter, data.SortColumn); 

如果我尝试像下面让我抓住从IRelationship的MemberExpression,但构建基于IContract拉姆达我从库中的错误。

 var parameter = Expression.Parameter(typeof(IRelationship)); 
     var memberExpression = Expression.Property(parameter, data.SortColumn); 
     var orderBy = Expression.Lambda(memberExpression, Expression.Parameter(typeof(IContract))); 

我得到的错误是“参数”没有绑定在指定的LINQ to Entities查询表达式中。

最终的表达得到它的工作是这样的

 var parameter = Expression.Parameter(typeof(IContract)); 
     var memberExpression = Expression.Property(parameter, typeof(IRelationship), data.SortColumn); 
     var orderBy = Expression.Lambda(memberExpression, parameter); 

所以,我需要到指定的中间参数的memberExpression线,说看在继承关系的接口的属性

+0

它是什么,你想表达呢?有一些方法可以使用'dynamic'来让它翻转成最合适的泛型重载,基本上避免了'MakeGenericMethod'。有用吗?例如:'IQueryable filtered = Queryable.Where(source,(dynamic)expression);' –

回答

17

你还挺需要使用正确的通用重载 - 这意味着你必须使用MakeGenericMethod;但是,您也可以使用dynamic,以避免需要在这里使用MakeGenericMethod,例如(通过Where在这种情况下,但重要的一点是它是如何工作):

IQueryable<Foo> source = new[] { new Foo { Bar = 123 } }.AsQueryable(); 
Expression<Func<Foo,bool>> typed = x=>x.Bar == 123; 

LambdaExpression untyped = typed; 
IQueryable<Foo> filtered = Queryable.Where(source, (dynamic)untyped); 

注意:您不能使用分机这里的方法 - 因此你需要使用Queryable.*

对于使用您的代码OrderBy例如:

var parameter = Expression.Parameter(typeof(Foo)); 
var memberExpression = Expression.Property(parameter, "Bar"); 
var lambdaExpression = Expression.Lambda(memberExpression, parameter); 
LambdaExpression untyped = lambdaExpression; 

IQueryable<Foo> sorted = Queryable.OrderBy(source, (dynamic)untyped); 

var all = sorted.ToArray(); 

重新编辑:

var parameter = Expression.Parameter(typeof(IRelationship)); 
var memberExpression = Expression.Property(
    Expression.Convert(parameter, typeof(IContract)), data.SortColumn); 
var orderBy = Expression.Lambda(memberExpression, parameter); 
+0

但是我需要调用的方法需要Expression-Func不是动态的,所以我不能传入动态。 –

+0

@PaulCavacas'Queryable.Where'和'Queryable.OrderBy' *也可以带一个Expression-Func,而不是一个动态的;这不是问题。关键是,这里使用'dynamic'使它可以工作*。魔法。 –

+0

我几乎有它的工作。剩下的一个问题。有疑问可以获得更多细节。 –

相关问题