我有一个名为HomeInfo
public class HomeInfo
{
public int ID {get;set;}
public string OwnerName {get;set;}
public string Address {get;set;}
public int EstimatedValue {get;set;}
}
我从服务器获取数据并将其添加到List<HomeInfo> listHomeInfo
现在在我的 GUI 中,我需要允许根据用户输入过滤结果,所以我的客户想要一个用于估计值的文本框,他想在那里输入文本,如“>30k 和 <50k”或“>50k”,我解析并转换了这些类的值和创建的对象
public class ExpressionValue
{
public float? FirstDigit { get; set; }
/// <summary>
/// >, >=, <,<=
/// </summary>
public string FirstExpCondition { get; set; }
/// <summary>
/// OR, AND
/// </summary>
public string ConditionOperator { get; set; }
public float SecondDigit { get; set; }
public string SecondExpCondition { get; set; }
}
使用 ExpressionValue 对象,我能够创建适当的条件字符串。现在我可以创建一个条件字符串,例如“EstimatedValue > 30000 AND EstimatedValue < 60000”或“EstimatedValue < 50000”
我不知道如何在“List listHomeInfo”上有效地应用此条件,因为据我所知List<T>.Where()
不支持字符串条件。我知道一种解决方法是将列表转换为 DataTable 并使用Select(string expression)
方法然后转换DataRow[]
为List<HomeInfo>
,但我认为可能有更好的方法来实现这一点。
[编辑]
我创建了两种方法来帮助我,但我得到了异常“二进制运算符 GreaterThan 没有为类型 'System.Single' 和 'System.Double' 定义。” 创建 BinaryExpression 时。
public static Expression<Func<T, bool>> ParseExpressionCondition<T>(string expression, string fieldName)
{
try
{
string decimalNumRegex = @"\d+(\.\d{1,2})?";
List<string> matchPatterns = new List<string>() { ">=", ">", "<=", "<" };
ExpressionValue expValue = new ExpressionValue();
Dictionary<string, string> conditions = new Dictionary<string, string>();
var parameter = Expression.Parameter(typeof(T), typeof(T).ToString());
//var lhs = Expression.GreaterThan(Expression.Property(parameter, "EstimatedValue"), Expression.Constant(30000));
BinaryExpression lhs = null, rhs = null;
object objectValue = null;
string condOperator = null;
foreach (string pattern in matchPatterns)
{
Match match = Regex.Match(expression, pattern + decimalNumRegex);
if (match.Success)
{
//get digit part
double digit = double.Parse(Regex.Match(match.Value, decimalNumRegex).Value);
if (!expValue.FirstDigit.HasValue)
{
objectValue = digit;
condOperator = match.Value.Replace(digit.ToString(), "");
lhs = GetBinaryExpression(parameter, fieldName, objectValue, condOperator);
}
else
{
objectValue = digit;
condOperator = match.Value.Replace(digit.ToString(), "");
rhs = GetBinaryExpression(parameter, fieldName, objectValue, condOperator);
}
}
}
if (expression.ToLower().Contains("and"))
return Expression.Lambda<Func<T, bool>>(Expression.And(lhs, rhs), parameter);
else if (expression.ToLower().Contains("or"))
return Expression.Lambda<Func<T, bool>>(Expression.Or(lhs, rhs), parameter);
return null;
}
catch (Exception ex)
{
Logger.WriteLog(ex);
throw ex;
}
}
private static BinaryExpression GetBinaryExpression(ParameterExpression paraExp, string fieldName, object expressionValue, string conditionOperator)
{
try
{
BinaryExpression binExp = null;
MemberExpression expressionLeft = Expression.Property(paraExp, fieldName);
Expression expressionRight = Expression.Constant(expressionValue );
switch (conditionOperator)
{
case ">":
binExp = Expression.GreaterThan(expressionLeft, expressionRight);
break;
case ">=":
binExp = Expression.GreaterThanOrEqual(expressionLeft, expressionRight);
break;
case "<":
binExp = Expression.LessThan(expressionLeft, expressionRight);
break;
case "<=":
binExp = Expression.LessThanOrEqual(expressionLeft, expressionRight);
break;
}
return binExp;
}
catch (Exception ex)
{
throw ex;
}
}