我有一个名为类HomeInfo
字符串条件<T>
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 EstimatedValue < 60000”或“EstimatedValue < 50000”
我不知道我怎样才能有效地对“名单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;
}
}
你为什么想要保存条件为一个字符串?它是由用户输入的吗?为什么不使用表达式树? –
'List.Where()不支持字符串条件' - 确实如此,如果字符串是你正在评估的条件。 –
这个例子看起来并不需要如此高度的自定义将查询放在一起,但总是有[动态LINQ库](http://weblogs.asp.net/scottgu/archive/2008/01 /07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx)。 – herzmeister