我有一个名为 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)
注意此 Get 的第二个参数是 Expression-Func-TEntity, TOrderBy。正如我所提到的,我有一个名为 sortColumn 的变量,它包含我的 TEntity 对象上的一个属性的字符串,我需要将该字符串转换为可以传递给 Get 方法的表达式。
这是我现在拥有的。
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 类型,那么它将正常工作。问题是我不知道表达式类型是什么,它可能是字符串、整数、整数?等。这完全取决于 sortColumn 属性中特定的属性类型。
你能帮我最后跳转到正确的表达式类型吗?
根据 Marc 的建议进行编辑: 我几乎有这个工作,实际上具体基于它正在工作的问题,但我还有 1 个问题。
作为我要查询的实体类型的 IContract 实际上继承自 IRelationship。如果我从 IContract 接口(interface)指定一个字段,那么上面的代码就可以工作。如果我从 IRelationship 接口(interface)指定一个字段,则以下行失败。
var memberExpression = Expression.Property(parameter, data.SortColumn);
如果我尝试类似下面的操作,以便从 IRelationship 中获取 MemberExpression,但基于 IContract 构建 Lambda,我会从存储库中收到错误。
var parameter = Expression.Parameter(typeof(IRelationship));
var memberExpression = Expression.Property(parameter, data.SortColumn);
var orderBy = Expression.Lambda(memberExpression, Expression.Parameter(typeof(IContract)));
我收到的错误是“参数 '' 未绑定(bind)到指定的 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 行中指定中间参数,也就是说在继承的 Relationship 接口(interface)中查找属性
最佳答案
您有点需要使用正确的泛型重载 - 这曾经意味着您必须使用 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);
关于c# - 从字符串属性名称创建通用表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18321019/