我正在编写一个查询框架,并尽量使其尽可能通用。
假设我有一个基于人的查询,我希望能够对名字和姓氏进行过滤,在这两种情况下我都希望能够使用过滤条件,例如StartsWith
,'{ {1}},EndsWith
,Contains
。
所以现在我有一个方法:
Equals
现在,我还希望能够为LastName构建相同的过滤器。将整个事情重新复制并粘贴,只是将private Expression<Func<Person, bool>> FirstNameFilter(Comparator comparator, string compareValue) {
switch (comparator) {
case Comparator.Equal:
return p => p.FirstName == compareValue;
case Comparator.Contains:
return p => p.FirstName.Contains(compareValue);
case Comparator.StartsWith:
return p => p.FirstName.StartsWith(compareValue);
// etc.
}
}
替换为p.FirstName
,这似乎是愚蠢而浪费的。我还有一些我想要过滤的其他字符串字段,我真的不想为每一个重写这整个方法!
是否有某种方法可以抽象出来,也许使用LinqKit,这样我就可以使用以下近似签名来提供更通用的方法:
p.LastName
这样我就可以在Expression<Func<Person, bool>> GetFilter(Expression<Func<Person, string>> stringExpression, Comparator comparator, string compareValue) {}
内调用它:
FirstNameFilter
答案 0 :(得分:3)
类似的东西(未经测试,但你有想法)应该可以帮助你构建所需的表达式:
public static class LinqQueries
{
private static MethodInfo toLowerMethod = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
private static MethodInfo startsWithMethod= typeof(String).GetMethod("StartsWith", new Type[] { typeof(String) });
private static MethodInfo containsMethod = typeof(String).GetMethod("Contains", new Type[] { typeof(String) });
private static MethodInfo endsWithMethod= typeof(String).GetMethod("EndsWith", new Type[] { typeof(String) });
public static Expression<Func<T, bool>> GetFilter(Expression<Func<T, string>> expression, Comparator comparator, string compareValue) {
ParameterExpression parameterExpression = null;
var memberExpression = GetMemberExpression(expression.Body, out parameterExpression);
Expression constExp = Expression.Constant(compareValue);
switch (comparator) {
case Comparator.Contains:
memberExpression = Expression.Call(memberExpression, containsMethod,constExp);
break;
case Comparator.StartsWith:
memberExpression = Expression.Call(memberExpression, startsWithMethod, constExp);
break;
//etc.
default :
memberExpression = Expression.Equal(memberExpression, constExp);
break;
}
return Expression.Lambda<Func<T, bool>>(memberExpression, new[]{parameterExpression});
}
private static Expression GetMemberExpression(Expression expression, out ParameterExpression parameterExpression)
{
parameterExpression = null;
if (expression is MemberExpression)
{
var memberExpression = expression as MemberExpression;
while (!(memberExpression.Expression is ParameterExpression))
memberExpression = memberExpression.Expression as MemberExpression;
parameterExpression = memberExpression.Expression as ParameterExpression;
return expression as MemberExpression;
}
if (expression is MethodCallExpression)
{
var methodCallExpression = expression as MethodCallExpression;
parameterExpression = methodCallExpression.Object as ParameterExpression;
return methodCallExpression;
}
return null;
}
}