C# 使用表达式树生成LINQ查询
更新 感谢Marc的帮助,如果有人感兴趣,可以参加AlphaPagedList课程 原创 我试图创建一个表达式树来返回以给定字符开头的元素C# 使用表达式树生成LINQ查询,c#,linq,lambda,expression-trees,C#,Linq,Lambda,Expression Trees,更新 感谢Marc的帮助,如果有人感兴趣,可以参加AlphaPagedList课程 原创 我试图创建一个表达式树来返回以给定字符开头的元素 IList<char> chars = new List<char>{'a','b'}; IQueryable<Dept>Depts.Where(x=> chars.Contains(x.DeptName[0])); 类似于(重新阅读问题后编辑的),但请注意,Expression.Invoke在3.5SP1中对EF
IList<char> chars = new List<char>{'a','b'};
IQueryable<Dept>Depts.Where(x=> chars.Contains(x.DeptName[0]));
类似于(重新阅读问题后编辑的),但请注意,Expression.Invoke在3.5SP1中对EF不起作用(但在LINQ to SQL中可以):
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Expressions;
班级部
{
公共字符串DeptName{get;set;}
}
公共静态类程序
{
静态void Main()
{
IList chars=新列表{'a','b'};
Dept[]depts=new[]{new Dept{DeptName=“alpha”},new Dept{DeptName=“beta”},new Dept{DeptName=“omega”};
var count=测试(depts.AsQueryable(),dept=>dept.DeptName,chars.count();
}
公共静态IQueryable测试(此IQueryable queryableData、表达式pi、IEnumerable字符)
{
var arg=表达式参数(typeof(T),“x”);
var prop=Expression.Invoke(pi,arg);
表达式体=null;
foreach(字符中的字符c){
表达式thisFilter=Expression.Call(prop,“StartsWith”,null,Expression.Constant(c.ToString());
body=body==null?thisFilter:Expression.OrElse(body,thisFilter);
}
var lambda=表达式.lambda(主体??表达式.常量(false),arg);
返回queryableData.Where(lambda);
}
}
太好了,非常感谢。我正在制作一个字母数字页面列表(沿着IPagedList的线条),这将是非常宝贵的。
public static IQueryable<T> testing<T>(this IQueryable<T> queryableData, Expression<Func<T,string>> pi, IEnumerable<char> chars)
{
// Compose the expression tree that represents the parameter to the predicate.
ParameterExpression pe = Expression.Parameter(queryableData.ElementType, "x");
ConstantExpression ch = Expression.Constant(chars,typeof(IEnumerable<char>));
// ***** Where(x=>chars.Contains(x.pi[0])) *****
// pi is a string property
//Get the string property
Expression first = Expression.Constant(0);
//Get the first character of the string
Expression firstchar = Expression.ArrayIndex(pi.Body, first);
//Call "Contains" on chars with argument being right
Expression e = Expression.Call(ch, typeof(IEnumerable<char>).GetMethod("Contains", new Type[] { typeof(char) }),firstchar);
MethodCallExpression whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
Expression.Lambda<Func<T, bool>>(e, new ParameterExpression[] { pe }));
// ***** End Where *****
return (queryableData.Provider.CreateQuery<T>(whereCallExpression));
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
class Dept
{
public string DeptName { get; set; }
}
public static class Program
{
static void Main()
{
IList<char> chars = new List<char>{'a','b'};
Dept[] depts = new[] { new Dept { DeptName = "alpha" }, new Dept { DeptName = "beta" }, new Dept { DeptName = "omega" } };
var count = testing(depts.AsQueryable(), dept => dept.DeptName, chars).Count();
}
public static IQueryable<T> testing<T>(this IQueryable<T> queryableData, Expression<Func<T,string>> pi, IEnumerable<char> chars)
{
var arg = Expression.Parameter(typeof(T), "x");
var prop = Expression.Invoke(pi, arg);
Expression body = null;
foreach(char c in chars) {
Expression thisFilter = Expression.Call(prop, "StartsWith", null, Expression.Constant(c.ToString()));
body = body == null ? thisFilter : Expression.OrElse(body, thisFilter);
}
var lambda = Expression.Lambda<Func<T, bool>>(body ?? Expression.Constant(false), arg);
return queryableData.Where(lambda);
}
}