我在使用 orderby linq
表达式中的动态参数时遇到问题
SearchExp函数
public Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q) { if (param == "to") return e => e.to_msg.Contains(q); else if (param == "from") return e => e.from_msg.Contains(q); else if (param == "cc") return e => e.cc_msg.Contains(q); else if (param == "bcc") return e => e.bcc_msg.Contains(q); else if (param == "subject") return e => e.subject.Contains(q); else return e => e.body_text.Contains(q); }
filterExp 函数
public Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value) { if (filter == "attachments") return e => e.attachments == value; else if (filter == "flagged") return e => e.flagged == value; else return e => e.seen == value; }
IQueryable 函数
private IQueryable SearchFilter(string param,string q,string filter, string value,string sort,string dir) { var searchXpr = SearchXpr(param, q); var filterXpr = FiltertXpr(filter, value); var emailmessage = db.EmailAflAwmMessage. Where(filterXpr).Where(searchXpr) .OrderByDescending(a => a.msg_date).Select(a => new { a.subject, a.msg_date, }); return emailmessage; }
上面的代码可以工作,但我需要动态方式的 OrderBy
。
因为我有 2 个参数 sort( 表示其参数名称) 和 dir ( 表示升序或降序) 就像我想要 orderby( 参数名称) dir
请帮助我,我感谢您的宝贵时间和建议,并以简单的方式向我建议任何替代方案。谢谢。
最佳答案
我建议您阅读Expression's tree's ,下面的代码是用于 didatic 的,但我认为这会对您有所帮助:
public static class ExpressionBuilder
{
private static readonly MethodInfo ToStringMethod = typeof(object).GetMethod("ToString");
private static readonly MethodInfo StringContainsMethod = typeof(string).GetMethod("Contains");
public static Func<T, object> Selector<T>(string prop)
{
var type = typeof(T);
var param = Expression.Parameter(type);
return Expression.Lambda<Func<T, object>>(Expression.Property(param, type.GetProperty(prop)), param).Compile();
}
public static Expression<Func<T, bool>> BuildFilterPredicate<T>(string q)
{
var query = Expression.Constant(q);
var type = typeof(T);
var lbdSelector = Expression.Parameter(type);
var predicates = type.GetProperties().SelectMany(p => PredicateContainsBuilder(lbdSelector, p, query)).ToList();
Expression body = predicates[0];
body = predicates.Skip(1).Aggregate(body, Expression.OrElse);
return Expression.Lambda<Func<T, bool>>(body, lbdSelector);
}
private static IEnumerable<MethodCallExpression> PredicateContainsBuilder(Expression lbdSelector, PropertyInfo prop, Expression query)
{
if (prop.PropertyType.IsClass)
return new List<MethodCallExpression> { Expression.Call(Expression.Call(Expression.Property(lbdSelector, prop), ToStringMethod), StringContainsMethod, query) };
var properties = prop.PropertyType.GetProperties();
return properties.Select(p => Expression.Call(Expression.Call(Expression.Property(lbdSelector, p), ToStringMethod), StringContainsMethod, query)).ToList();
}
}
所以现在你在你的方法中执行此操作:
Note:
- I supose that the entity is EmailMessage so i use that to generate the predicate;
- It doesn't search in depth;
- it will search in all properties and doesn't use the
string param
to define what property to match;
private IQueryable SearchFilter(string param,string q,string filter,string value,string sort,string dir)
{
var emailMessage = db.EmailAflAwmMessage
.Where(ExpressionBuilder.BuildFilterPredicate<EmailMessage>(q))
.OrderBy(ExpressionBuilder.Selector<EmailMessage>(sort))
.Select(m=> new{m.subject,m.msg_date});
return emailmessage;
}
关于c# - 如何在 orderby 子句中使用带有动态参数的 LINQ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34236345/