我正在创建一个动态表达式,它将按一些规则(lambda exp。)对列表中的项进行排序。这是代码:
Expression<Func<String, String>> exp = o => o;
MethodCallExpression orderByExp = Expression.Call(typeof(Enumerable), "OrderBy",
new Type[] { typeof(String), exp.Body.Type }, Expression.Parameter(typeof(IEnumerable<String>), "list"), exp);
现在我想在特定数据上执行以前创建的表达式来对其进行排序,但由于一些奇怪的异常,例如“Lambda参数不在范围内”或“参数表达式无效”,它会失败。
var data = new String[] { "asdasdasd", "asdads", "123", "xcvxcvs", "ASDSD" };
// one of attempts: doesn't work
var result = data.AsQueryable().Provider.CreateQuery<String>(orderByExp);
有人可以帮我吗?
答案 0 :(得分:3)
按属性排序任何可枚举(无反射):
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> items, string property, bool ascending)
{
var MyObject = Expression.Parameter(typeof (T), "MyObject");
var MyEnumeratedObject = Expression.Parameter(typeof (IEnumerable<T>), "MyEnumeratedObject");
var MyProperty = Expression.Property(MyObject, property);
var MyLamda = Expression.Lambda(MyProperty, MyObject);
var MyMethod = Expression.Call(typeof(Enumerable), ascending ? "OrderBy" : "OrderByDescending", new[] { typeof(T), MyLamda.Body.Type }, MyEnumeratedObject, MyLamda);
var MySortedLamda = Expression.Lambda<Func<IEnumerable<T>, IOrderedEnumerable<T>>>(MyMethod, MyEnumeratedObject).Compile();
return MySortedLamda(items);
}
答案 1 :(得分:2)
这是工作代码:
Expression<Func<String, String>> exp = o => o;
var list = Expression.Parameter(typeof(IEnumerable<String>), "list");
MethodCallExpression orderByExp = Expression.Call(typeof(Enumerable), "OrderBy",
new Type[] { typeof(String), exp.Body.Type }, list, exp);
var lambda = Expression.Lambda<Func<IEnumerable<String>, IEnumerable<String>>>(orderByExp, list);
var data = new String[] { "asdasdasd", "asdads", "123", "xcvxcvs", "ASDSD" };
var result = lambda.Compile()(data);
感谢专家
答案 2 :(得分:1)
我遇到了与Linq几乎相同的问题,我决定编写一个扩展函数,其中一些想法来自这个问题的答案:
<Extension()> _
Public Function OrderBy(Of T)(ByVal query As IEnumerable(Of T), ByVal sortColumn As String, ByVal direction As String) As IEnumerable(Of T)
Dim methodName As String = String.Format("OrderBy{0}", If(direction.ToLower() = "asc", "", "Descending"))
Dim parameter As ParameterExpression = Expression.Parameter(GetType(T), "p")
Dim memberAccess As MemberExpression = Nothing
For Each _property As Object In sortColumn.Split(".")
memberAccess = MemberExpression.Property(If(memberAccess, CType(parameter, Expression)), _property)
Next
Dim orderByLambda As LambdaExpression = Expression.Lambda(memberAccess, parameter)
'
Dim myEnumeratedObject As ParameterExpression = Expression.Parameter(GetType(IEnumerable(Of T)), "MyEnumeratedObject")
Dim result As MethodCallExpression = Expression.Call(GetType(Enumerable), _
methodName, _
New System.Type() {GetType(T), memberAccess.Type}, _
myEnumeratedObject, _
orderByLambda)
Dim lambda = Expression.Lambda(Of Func(Of IEnumerable(Of T), IEnumerable(Of T)))(result, myEnumeratedObject)
Return lambda.Compile()(query)
End Function
答案 3 :(得分:0)
有什么特别的原因你不只是打电话:
data.AsQueryable().OrderBy(exp);
你甚至需要在这里使用IQueryable
吗?我觉得我错过了一些大局。你真的要把它作为LINQ to SQL(或LINQ to Entities)的一部分来调用吗?如果它只是在LINQ to Objects中,你不能只使用data.OrderBy(exp)
吗?
基本上,更多解释会有所帮助:)