我已经找到了类似概念的答案,但似乎都不适合我的情况。
我正在构建一个对象,该对象通过 Where 子句和运行时已知类型的 Lambda 过滤结果。
过滤器数组可以包含一个或多个过滤器,这些过滤器具有属性名称和相等运算符(即 gte、eq、neq 等)和要比较的值。
由于我可以有多个属性要过滤,因此我首先获取比较任何对象属性所需的所有 BinaryExpression并将它们合并到传递给查询 Where 子句的单个表达式中。
如果筛选器的属性类型是 DateTime,我只想使用 BinaryExpression 比较属性的 Date 部分。
我有一个接收过滤器的参数名称及其值的方法。
public static Expression<Func<T, bool>> GetEqualExpression<T>(string parameterName,
string comparisonValue) {
var param = Expression.Parameter(typeof(T), parameterName);
var property = Expression.Property(param, parameterName);
var propInfo = (PropertyInfo) property.Member;
var propType = propInfo.PropertyType;
if (propType == typeof(DateTime)) {
// Parse the string to a DateTime.
const string dateFormat = "ddd MMM d yyyy HH:mm:ss 'GMT'K";
var parsedDate = DateTime.ParseExact(comparisonValue, dateFormat, CultureInfo.InvariantCulture);
// Trying to access the 'Date' child property.
property = Expression.Property(property, "Date");
var constant = Expression.Constant(parsedDate.Date);
return Expression.Lambda<Func<T, bool>>(Expression.Equal(property, constant), param);
}
...
}
例如,将对象视为:
public class Ticket {
public DateTime StartDate {get; set;}
public DateTime DueDate {get; set;}
}
以及"StartDate"属性的过滤器,当我将表达式传递给查询的 where 子句时,它会失败并出现异常"Lambda 参数不在范围内"。
我错过了什么?
提前谢谢你。
更新
因此,多亏了xanatos,我发现ServiceStack.OrmLite(我正在使用的ORM)不支持访问Date属性,就像EF一样。所以现在的问题是,我该如何解决这种情况?
所以,这就是我处理这种情况的方式。我真的要感谢xanatos指出ORM的DateTime.Date问题。
我决定通过以下方式按时间范围比较日期相等性:
public static Expression<Func<T, bool>> GetEqualExpression(string parameterName,
string comparisonValue)
{
var param = Expression.Parameter(typeof (T), parameterName);
var prop = Expression.Property(param, parameterName);
var propInfo = (PropertyInfo) Property.Member;
var propType = propInfo.PropertyType;
if (propType == typeof(DateTime))
{
const string dateFormat = "ddd MMM d yyyy HH:mm:ss 'GMT'K";
var parsedDate = DateTime.ParseExact(comparisonValue, dateFormat, CultureInfo.InvariantCulture);
var dayStart = new DateTime(parsedDate.Year, parsedDate.Month, parsedDate.Day, 0, 0, 0, 0);
var dayEnd = new DateTime(parsedDate.Year, parsedDate.Month, parsedDate.Day, 23, 59, 59, 999);
var left = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(prop, Expression.Constant(dayStart)), param);
var right = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(prop, Expression.Constant(dayEnd)), param);
return left.Compose(right, Expression.And);
}
...
}
这似乎可以解决问题。
有一个小错误:你必须使用
Expression.Equal(property, constant)
而不是
Expression.Equals(property, constant)
然后,也许您在 由于我可以有多个属性要过滤,因此我首先获取所有需要比较任何对象属性的 BinaryExpression 并将它们合并到传递给查询 Where 子句部分的单个表达式中
请注意,如果您使用的是实体框架,则可能不支持该DateTime.Date
。请参阅 https://stackoverflow.com/a/21186498/613130 。一种可能的解决方案是使用 EntityFunctions.TruncateTime
.