我创建了一个帮助器类,它能够从字符串参数构建lambda表达式,我可以使用它来过滤查询结果。
但我没有问题,LINQ.Expressions.Expression没有Contains方法。
这是我的代码:
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);
}
应该可以工作,但我可以将Expression转换为BinaryExpression?
有人知道这个或知道其他有效的解决方案吗?
答案 0 :(得分:0)
我知道问这个问题已经有很长时间了,但是,我认为我已经找到了答案,基本上,答案在MakeBinary
上。
首先,我必须创建一个类似Contains的方法,但不能创建一个自引用扩展方法,例如:
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; }
}
}
答案 1 :(得分:-2)
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
}
}