public static Expression<Func<T, bool>> SearchExpression<T>(string[] propertyNames, string[] propertyValue){
var parameterExp = Expression.Parameter(typeof(T), "type");
MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes);
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
List<Expression> methodCalls = new List<Expression>();
Expression finalExpression = Expression.Constant(true);
foreach (string propertyName in propertyNames)
{
var propertyExp = Expression.Property(parameterExp, propertyName);
var queryValue = Expression.Constant(propertyValue[Array.IndexOf(propertyNames, propertyName)].ToLower(), typeof(string));
var exp = Expression.NotEqual(propertyExp, Expression.Constant(null, typeof(object)));
methodCalls.Add(exp);
var toLowerMethodExp = Expression.Call(propertyExp, toLowerMethod);
var containsMethodExp = Expression.Call(toLowerMethodExp, "Contains", Type.EmptyTypes, queryValue);
methodCalls.Add(containsMethodExp);
}
var orExp = methodCalls.Aggregate((left, right) => Expression.And(left, right));
return Expression.Lambda<Func<T, bool>>(orExp, parameterExp);
}
当我尝试调试它时,它显示了完美的表达式,但是当在db列中有null
值时它会给出错误。
答案 0 :(得分:0)
您应该使用Expression.AndAlso
来组合方法调用。
Expression.And
是按位的 - Expression.AndAlso
是短路评估的逻辑和。
请参阅https://msdn.microsoft.com/en-us/library/bb353520(v=vs.110).aspx
答案 1 :(得分:-1)
public static Expression<Func<T, bool>> Search<T>(string[] propertyNames, string[] propertyValue,bool isOr = false)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "c");
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Where(p => p.PropertyType == typeof(string) && propertyNames.Contains(p.Name));
Expression orExpressions = null;
MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", Type.EmptyTypes);
foreach (var callContainsMethod in from property in publicProperties
let myProperty = Expression.Property(parameter, property.Name)
let toLowerMethodExp = Expression.Call(myProperty, toLowerMethod)
let myExpression = Expression.Call(toLowerMethodExp, "Contains", null, Expression.Constant(propertyValue[Array.IndexOf(propertyNames, property.Name)].ToLower()))
let myNullExp = Expression.Call(typeof(string), (typeof(string).GetMethod("IsNullOrEmpty")).Name, null, myProperty)
let myNotExp = Expression.Not(myNullExp)
select new { myExpression, myNotExp })
{
var andAlso = Expression.AndAlso(callContainsMethod.myNotExp, callContainsMethod.myExpression);
if (orExpressions == null)
{
orExpressions = andAlso;
}
else
{
if(!isOr)
orExpressions = Expression.And(orExpressions, andAlso);
else
orExpressions = Expression.Or(orExpressions, andAlso);
}
}
return Expression.Lambda<Func<T, bool>>(orExpressions, parameter);
}