我有一个将lambda添加到IQueryable的泛型方法。下面的一个添加了一个StartsWith lambda。我现在要做的是创建一个NotStartsWith lambda。由于NotStartsWith不是字符串运算符,我不知道从哪里开始。
我认为(应该)是一种构建处理否定操作的EpressionTree的方法。但看起来它们都适用于Type上的当前方法调用,所以我的下一个想法是做一个IndexOf并测试!= 0。
因为我确定我需要解决方案来处理其他运算符,所以我希望找到一种创建lambda的方法,我可以在其中进行方法调用并将该结果与另一个常量进行比较,即(字符串) .Substring(3,7)==“abcd”。我只是想不出一种在ExpressionTree中进行比较的方法。
这就是我对StartsWith所做的,它运行正常。我只是需要一种方法来否定它或(甚至更好的未来操作)找到一种方法来构建表达式与比较。
static IQueryable<T> ETForStartsWith<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo)
{
ParameterExpression e = Expression.Parameter(typeof(T), "e");
MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
Expression call = Expression.Call(m, mi, c);
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e);
return query.Where(lambda);
}
感谢您的帮助!
答案 0 :(得分:0)
只需negate方法调用结果:
/// <summary>
/// Adds "Where(_ => !_.StringProperty.StartsWith("someValue"))" to the query.
/// </summary>
static IQueryable<T> AddNotStartsWith<T>(IQueryable<T> query, PropertyInfo propertyInfo, string value)
{
var parameter = Expression.Parameter(typeof(T));
var memberAccess = Expression.MakeMemberAccess(parameter, propertyInfo);
var startsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
var methodCall = Expression.Call(memberAccess, startsWithMethod, Expression.Constant(value));
return query
.Where(Expression.Lambda<Func<T, bool>>(Expression.Not(methodCall), parameter));
}
或以更通用的方式:
static IQueryable<T> AddComparisonExpression<T>(IQueryable<T> query, PropertyInfo propertyInfo, Func<Expression, Expression> getComparisonExpression)
{
var parameter = Expression.Parameter(typeof(T));
var memberAccess = Expression.MakeMemberAccess(parameter, propertyInfo);
return query
.Where(Expression.Lambda<Func<T, bool>>(getComparisonExpression(memberAccess), parameter));
}
/// <summary>
/// Adds "Where(_ => !_.StringProperty.StartsWith("someValue"))" to the query.
/// </summary>
static IQueryable<T> AddNotStartsWith<T>(IQueryable<T> query, PropertyInfo propertyInfo, string value)
{
return AddComparisonExpression(query, propertyInfo, memberAccess =>
{
var startsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
var methodCall = Expression.Call(memberAccess, startsWithMethod, Expression.Constant(value));
return Expression.Not(methodCall);
});
}
/// <summary>
/// Adds "Where(_ => _.StringProperty.Substring(startIndex, length) == value)" to the query.
/// </summary>
static IQueryable<T> AddSubstringEquals<T>(IQueryable<T> query, PropertyInfo propertyInfo, int startIndex, int length, string value)
{
return AddComparisonExpression(query, propertyInfo, memberAccess =>
{
var substringMethod = typeof(string).GetMethod("Substring", new[] { typeof(int), typeof(int) });
var methodCall = Expression.Call(memberAccess, substringMethod, Expression.Constant(startIndex), Expression.Constant(length));
return Expression.Equal(methodCall, Expression.Constant(value));
});
}