我正在尝试首先过滤一组产品,然后订购它们
(repository.GetAllProducts()
.Where(x=>x.Naam.Contains("filter")) as ObjectQuery<Product>)
.FunkyOrder<Product>(sortfield,sortdirection)
使用Extension方法:
public static IEnumerable<T> FunkyOrder<T>(this ObjectQuery<T> input, string fieldname = "Id", string sortdirection = "asc")
{
switch (sortdirection)
{
case "dsc":
case "desc":
return input.OrderBy("it." + fieldname + " DESC");
default:
return input.OrderBy("it." + fieldname);
}
}
(我的Repository的GetAllProducts()返回一个IEnumerable
这个FunkyOrder方法应该可以工作但是 - 作为ObjectQuery - cast返回NULL
我只能将FunkyOrder与ObjectQuery一起使用,因为这似乎是唯一支持那些“it.FieldName”查询的东西。
如果我将 - as - notation更改为常规演员,我会得到:
Unable to cast object of type 'WhereEnumerableIterator`1[MySecretNameSpace.Product]' to type 'System.Data.Objects.ObjectQuery`1[MySecretNameSpace.Product]'.
有没有办法让这项工作或者我会被迫在过滤前使用排序,或者为我的排序编写一个带有lambda表达式的巨型开关?
答案 0 :(得分:7)
这实际上是一个试图解决的巨大头痛;但最终,它实际上很容易通过一些hackishness和反思完成:
public class Program
{
public class SomeClass
{
public int Id { get; set; }
public string Name { get; set; }
}
static void Main(string[] args)
{
List<SomeClass> sample = new List<SomeClass>
{
new SomeClass { Id = 4, Name = "ABC" },
new SomeClass { Id = 1, Name = "XYZ" },
new SomeClass { Id = 2, Name = "JKL" }
};
var result = sample.OrderByDynamic("Name", OrderDirection.Ascending).ToList();
result.ForEach(x => Console.WriteLine("Id: " + x.Id + " | Name: " + x.Name));
Console.ReadKey();
}
}
public enum OrderDirection
{
Ascending,
Descending
}
public static class LinqExtensions
{
public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, OrderDirection direction = OrderDirection.Ascending)
{
if(direction == OrderDirection.Ascending)
return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
else
return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null));
}
}
这个例子在测试情况下对我有用;我可以提供属性名称,并指定排序方向,它工作得很好。只需像这样打电话:
yourEnumerable.OrderByDynamic("YourPropertyName");
yourEnumerable.OrderByDynamic("YourPropertyName", OrderDirection.Descending);
享受!
答案 1 :(得分:2)
我会将你的FunkyOrder方法更改为IEnumerable并通过动态创建一个表达式实现动态排序
public static IEnumerable<T> FunkyOrder<T, TResult>(this IEnumerable<T> input, string fieldname = "Id", string sortdirection = "asc")
{
ParameterExpresssion parameter = Expression.Parameter(typeof(T), "p");
Expression property = Expression.PropertyOrField(parameter, fieldname);
var lambda = Expression.Lambda<Func<T, TResult>>(property, parameter)
if(sortdirection == "asc")
{
return input.OrderBy(lambda.Compile());
}
else
{
return input.OrderByDescending(lambda.Complile());
}
}
您将不再需要转换为ObjectQuery
答案 2 :(得分:1)
您可以使用Dynamic Linq进行动态过滤和排序。这个小型库(只有一个源文件)包含IQueryable<T>
的扩展方法,如:
public static IQueryable<T> Where<T>(this IQueryable<T> source,
string predicate, params object[] values)
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,
string ordering, params object[] values)
//...and more like GroupBy, Select
您对IEnumerable的查询可以写成:
repository.GetAllProducts().AsQueryable()
.Where(x => x.Naam.Contains("filter"))
.OrderBy("FieldName desc")
库实现了执行这些动态查询所需的所有反射代码。