我有一个通用表达式构建器,其代码如下:
public class EntityExpression
{
public enum Op
{
Equals,
GreaterThan,
LessThan,
GreaterThanOrEqual,
LessThanOrEqual,
Contains,
StartsWith,
EndsWith,
Nothing,
StringEquals
}
public class Filter
{
public string PropertyName { get; set; }
public Op Operation { get; set; }
public object Value { get; set; }
public static Op Operatorstranslation(string InputOperator)
{
switch (InputOperator)
{
case "eq":
return Op.Equals;
case "startswith":
return Op.StartsWith;
case "contains":
return Op.Contains;
}
return Op.Nothing;
}
}
public static class ExpressionBuilder
{
private static MethodInfo containsMethod = typeof(string).GetMethod("Contains" );
private static MethodInfo startsWithMethod = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
private static MethodInfo endsWithMethod = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
private static MethodInfo compareMethod = typeof(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string), typeof(StringComparison) });
public static Expression<Func<T, bool>> GetExpression<T>(IList<Filter> filters)
{
if (filters.Count == 0)
return null;
ParameterExpression param = Expression.Parameter(typeof(T), "t");
Expression exp = null;
if (filters.Count == 1)
exp = GetExpression<T>(param, filters[0]);
else if (filters.Count == 2)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
{
while (filters.Count > 0)
{
var f1 = filters[0];
var f2 = filters[1];
if (exp == null)
exp = GetExpression<T>(param, filters[0], filters[1]);
else
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0], filters[1]));
filters.Remove(f1);
filters.Remove(f2);
if (filters.Count == 1)
{
exp = Expression.AndAlso(exp, GetExpression<T>(param, filters[0]));
filters.RemoveAt(0);
}
}
}
return Expression.Lambda<Func<T, bool>>(exp, param);
}
private static Expression GetExpression<T>(ParameterExpression param, Filter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
// ConstantExpression valueExpression = Expression.Constant(filter.Value);
var propertyType = ((PropertyInfo)member.Member).PropertyType;
var converter = TypeDescriptor.GetConverter(propertyType);
if (!converter.CanConvertFrom(typeof(string))) // 2
throw new NotSupportedException();
var propertyValue = converter.ConvertFromInvariantString(filter.Value.ToString());
var constant = Expression.Constant(propertyValue);
var valueExpression = Expression.Convert(constant, propertyType);
ConstantExpression stringComparisonConstant = Expression.Constant(StringComparison.OrdinalIgnoreCase);
switch (filter.Operation)
{
case Op.Equals:
return Expression.Equal(member, valueExpression);
case Op.GreaterThan:
return Expression.GreaterThan(member, valueExpression);
case Op.GreaterThanOrEqual:
return Expression.GreaterThanOrEqual(member, valueExpression);
case Op.LessThan:
return Expression.LessThan(member, valueExpression);
case Op.LessThanOrEqual:
return Expression.LessThanOrEqual(member, valueExpression);
case Op.Contains:
return Expression.Call(member, containsMethod, valueExpression);
case Op.StringEquals:
var zeroConstant = Expression.Constant(0);
var compareExpression = Expression.Call(compareMethod, member, valueExpression, stringComparisonConstant);
return Expression.Equal(compareExpression, zeroConstant);
case Op.StartsWith:
return Expression.Call(member, startsWithMethod, valueExpression);
case Op.EndsWith:
return Expression.Call(member, endsWithMethod, valueExpression);
}
return null;
}
private static BinaryExpression GetExpression<T>
(ParameterExpression param, Filter filter1, Filter filter2)
{
Expression bin1 = GetExpression<T>(param, filter1);
Expression bin2 = GetExpression<T>(param, filter2);
return Expression.AndAlso(bin1, bin2);
}
}
}
我的问题是这段代码不适用于不区分大小写的情况,尤其是containsMethod
,显然是因为该操作中没有空闲代码,但是compareMethod
可以完全适用于任何情况,因为正确的代码用于不敏感。
我希望我的containsMethod
适用于任何情况(上方或下方)。任何人都可以帮我这个代码吗?