Linq 二进制表达式包含方法
我创建了一个helper类,它能够从字符串参数构建lambda表达式,我可以使用它过滤查询结果 但是我有一个小问题,LINQ.Expressions.Expression没有Contains方法 这是我的代码:Linq 二进制表达式包含方法,linq,c#-4.0,expression-trees,Linq,C# 4.0,Expression Trees,我创建了一个helper类,它能够从字符串参数构建lambda表达式,我可以使用它过滤查询结果 但是我有一个小问题,LINQ.Expressions.Expression没有Contains方法 这是我的代码: string member = d.Member; object value = d.Value; System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expr
string member = d.Member;
object value = d.Value;
System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");
foreach (var property in member.Split('.'))
{
expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
}
ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string));
BinaryExpression b = null;
switch (d.Operator)
{
case FilterOperator.IsEqualTo:
b = System.Linq.Expressions.Expression.Equal(expression, c);
break;
case FilterOperator.Contains:
b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression;
break;
case FilterOperator.IsGreaterThanOrEqualTo:
b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c);
break;
case FilterOperator.IsLessThanOrEqualTo:
b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c);
break;
}
CriteriaCollection.Add(b);
static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}
字符串成员=d.成员;
对象值=d.值;
System.Linq.Expressions.Expression=System.Linq.Expressions.Expression.Parameter(typeof(T),“e”);
foreach(member.Split('.')中的var属性)
{
expression=System.Linq.Expressions.expression.PropertyOrField(expression,property);
}
ConstantExpression c=System.Linq.Expressions.Expression.Constant(value,typeof(string));
二进制表达式b=null;
开关(d.操作员)
{
case FilterOperator.IsEqualTo:
b=System.Linq.Expressions.Expression.Equal(表达式c);
打破
案例过滤器操作器。包含:
b=GetExpression(expression.ToString(),value.ToString())。主体为二进制表达式;
打破
案例过滤器Operator.Is大于或等于:
b=System.Linq.Expressions.Expression.GreaterThanOrEqual(表达式,c);
打破
案例过滤器Operator.islessthan或equalto:
b=System.Linq.Expressions.Expression.lessthanRequal(表达式,c);
打破
}
标准收集。添加(b);
静态表达式GetExpression(string propertyName、string propertyValue)
{
var parameterExp=表达式参数(typeof(T),“type”);
var propertyExp=Expression.Property(parameterExp,propertyName);
MethodInfo method=typeof(string).GetMethod(“Contains”,new[]{typeof(string)});
var someValue=表达式.常量(propertyValue,typeof(字符串));
var containsMethodExp=Expression.Call(propertyExp,method,someValue);
返回BinaryExpression.Lambda(containsMethodExp,parameterExp);
}
这应该是可行的,但是如何将表达式转换为二进制表达式呢
有人知道这一点,或者知道其他正在运行的解决方案吗?公共类筛选器ExpressionHelper其中T:class
public class FilterExpressionHelper<T> where T : class
{
public FilterExpressionHelper()
{
CriteriaCollection = new List<BinaryExpression>();
}
public List<BinaryExpression> CriteriaCollection { get; set; }
public Expression<Func<T, bool>> NoFilterExpression { get; set; }
public void RemoveFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
{
string member = d.Member;
object value = d.Value;
System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");
foreach (var property in member.Split('.'))
{
expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
}
ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, typeof(string));
BinaryExpression b = System.Linq.Expressions.Expression.Equal(expression, c);
BinaryExpression expr = CriteriaCollection.Where(cr => cr.Right.ToString() == b.Right.ToString()).FirstOrDefault();
CriteriaCollection.Remove(expr);
}
public void AddFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
{
string member = d.Member;
object value = d.Value;
System.Linq.Expressions.Expression expression = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");
foreach (var property in member.Split('.'))
{
expression = System.Linq.Expressions.Expression.PropertyOrField(expression, property);
}
ConstantExpression c = System.Linq.Expressions.Expression.Constant(value, value.GetType());
BinaryExpression b = null;
switch (d.Operator)
{
case FilterOperator.IsEqualTo:
b = System.Linq.Expressions.Expression.Equal(expression, c);
break;
case FilterOperator.Contains:
//b = GetExpression<T>(expression.ToString(), value.ToString()).Body as BinaryExpression;
break;
case FilterOperator.IsGreaterThanOrEqualTo:
b = System.Linq.Expressions.Expression.GreaterThanOrEqual(expression, c);
break;
case FilterOperator.IsLessThanOrEqualTo:
b = System.Linq.Expressions.Expression.LessThanOrEqual(expression, c);
break;
}
CriteriaCollection.Add(b);
}
public Expression<Func<T, bool>> GetLambdaExpression()
{
ParameterExpression e = System.Linq.Expressions.Expression.Parameter(typeof(T), "e");
var orderedList = CriteriaCollection.OrderBy(cr => cr.Left.ToString()).ToList();
var disctinctValues = CriteriaCollection.Distinct(new BinaryExpressionComparer()).ToList();
List<BinaryExpression> orElseExpressionList = new List<BinaryExpression>();
foreach (var value in disctinctValues)
{
System.Linq.Expressions.BinaryExpression expression = null;
foreach (var criteria in orderedList.Where(cr => cr.Left.ToString().Equals(value.Left.ToString())))
{
if (expression == null)
{
expression = criteria;
}
else
{
if (expression.Left.ToString() == criteria.Left.ToString())
expression = System.Linq.Expressions.BinaryExpression.OrElse(expression, criteria);
else
expression = System.Linq.Expressions.BinaryExpression.AndAlso(expression, criteria);
}
}
orElseExpressionList.Add(expression);
}
System.Linq.Expressions.BinaryExpression expressionAnd = null;
foreach (var ex in orElseExpressionList)
{
if (expressionAnd == null)
{
expressionAnd = ex;
}
else
{
expressionAnd = System.Linq.Expressions.BinaryExpression.AndAlso(expressionAnd, ex);
}
}
if (expressionAnd != null)
{
return System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(expressionAnd, e);
}
else
{
return NoFilterExpression;
}
}
static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
{
var parameterExp = Expression.Parameter(typeof(T), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);
return BinaryExpression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}
private static System.Linq.Expressions.BinaryExpression Like(Expression lhs, Expression rhs)
{
//typeof(string).GetMethod("Contains", new Type[] { typeof(string) }, null);
Expression expression = Expression.Call(
typeof(FileInfoHelper).GetMethod("Like",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
, lhs, rhs);
return expression as BinaryExpression;
}
class BinaryExpressionComparer : IEqualityComparer<BinaryExpression>
{
#region IEqualityComparer<Contact> Members
public bool Equals(BinaryExpression x, BinaryExpression y)
{
return x.Left.ToString().Equals(y.Left.ToString());
}
public int GetHashCode(BinaryExpression obj)
{
return obj.Left.ToString().GetHashCode();
}
#endregion
}
}
{
公共筛选器ExpressionHelper()
{
CriteriaCollection=新列表();
}
公共列表标准集合{get;set;}
公共表达式NoFilterExpression{get;set;}
public void RemoveFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
{
字符串成员=d.成员;
对象值=d.值;
System.Linq.Expressions.Expression=System.Linq.Expressions.Expression.Parameter(typeof(T),“e”);
foreach(member.Split('.')中的var属性)
{
expression=System.Linq.Expressions.expression.PropertyOrField(expression,property);
}
ConstantExpression c=System.Linq.Expressions.Expression.Constant(value,typeof(string));
BinaryExpression b=System.Linq.Expressions.Expression.Equal(表达式c);
二进制表达式expr=CriteriaCollection.Where(cr=>cr.Right.ToString()==b.Right.ToString()).FirstOrDefault();
标准集合。删除(expr);
}
public void AddFilterCriteriaFilterDescriptor(Telerik.Windows.Data.FilterDescriptor d)
{
字符串成员=d.成员;
对象值=d.值;
System.Linq.Expressions.Expression=System.Linq.Expressions.Expression.Parameter(typeof(T),“e”);
foreach(member.Split('.')中的var属性)
{
expression=System.Linq.Expressions.expression.PropertyOrField(expression,property);
}
ConstantExpression c=System.Linq.Expressions.Expression.Constant(value,value.GetType());
二进制表达式b=null;
开关(d.操作员)
{
case FilterOperator.IsEqualTo:
b=System.Linq.Expressions.Expression.Equal(表达式c);
打破
案例过滤器操作器。包含:
//b=GetExpression(expression.ToString(),value.ToString())。主体为二进制表达式;
打破
案例过滤器Operator.Is大于或等于:
b=System.Linq.Expressions.Expression.GreaterThanOrEqual(表达式,c);
打破
案例过滤器Operator.islessthan或equalto:
b=System.Linq.Expressions.Expression.lessthanRequal(表达式,c);
打破
}
标准收集。添加(b);
}
公共表达式GetLambdaExpression()
{
ParameterExpression e=System.Linq.Expressions.Expression.Parameter(typeof(T),“e”);
var orderedList=CriteriaCollection.OrderBy(cr=>cr.Left.ToString()).ToList();
var disctinctValues=CriteriaCollection.Distinct(新的BinaryExpressionComparer()).ToList();
List ORELSExpressionList=新列表();
foreach(disctinctValues中的var值)
{
System.Linq.Expressions.BinaryExpression=null;
foreach(orderedList.Where(cr=>cr.Left.ToString().Equals(value.Left.ToString()))中的var条件)
{
if(表达式==null)
{
表达式=标准;
}
其他的
{
if(expression.Left.ToString()==criteria.Left.ToString())
expression=System.Linq.Expressions.BinaryExpression.OrElse(表达式,条件);
其他的
expression=System.Linq.Expressions.BinaryExpression.AndAlso(表达式,条件);
}
}
添加(表达式);
}
System.Linq.Expressions.BinaryExpression expression and=null;
foreach(OrelSexpressionList中的var ex)
{
if(expressionAnd==null)
public static bool Containss(string text, string text2)
{
return text.Contains(text2, StringComparison.OrdinalIgnoreCase);
}
MethodInfo method = typeof(StackOverflowAnswer).GetMethod("Containss", new[] { typeof(string), typeof(string) });
var constainsExp = Expression.MakeBinary(ExpressionType.Equal, Expression.Constant("FULL TEXT"), Expression.Constant("TEXT"), false, method);
class StackOverflowAnswer
{
static void Main()
{
ParameterExpression parameter = Expression.Parameter(typeof(Student), typeof(Student).Name);
var exp1 = GetBinaryExpression(parameter, "Name", "Foo");
var exp2 = GetBinaryExpression(parameter, "Name", "Bar");
BinaryExpression[] expressions = new BinaryExpression[] { exp1, exp2 };
var bin = CombineExpressions(expressions, parameter);
var func = Expression.Lambda<Func<Student, bool>>(bin, parameter);
var exp = func.Compile();
Student student = new Student { Name = "Foo Bar" };
var x = exp(student);
Console.WriteLine(x);
}
public static BinaryExpression GetBinaryExpression(ParameterExpression parameter, string property, object comparissonValue)
{
MemberExpression member = Expression.Property(parameter, property);
ConstantExpression constant = Expression.Constant(comparissonValue, comparissonValue.GetType());
MethodInfo method = typeof(StackOverflowAnswer).GetMethod("Containss", new[] { typeof(string), typeof(string) });
var containsExp = Expression.MakeBinary(ExpressionType.Equal, member, constant, false, method);
return containsExp ;
}
public static BinaryExpression CombineExpressions(BinaryExpression[] expressions, ParameterExpression parameter)
{
bool first = true;
BinaryExpression expFull = expressions[0];
foreach (BinaryExpression item in expressions)
{
if (first)
first = false;
else
{
expFull = Expression.AndAlso(expFull, item);
}
}
return expFull;
}
internal class Student
{
public string Name { get; set; }
}
}