具有泛型属性的 LINQ 表达式
本文关键字:LINQ 表达式 属性 泛型 | 更新日期: 2023-09-27 18:32:11
我的问题与此有关:linq-expression-with-generic-class-properties
这次我想获得具有共同 id 的新创建对象。id 实际上是外键,因此可以有不同的名称。
我想出了以下内容:
public static IEnumerable<T> GetNew<TId, T>(IQueryable<T> objects, TId id, DateTime date, Expression<Func<T, TId>> idSelector)
where T : class, ISyncable<TId>
{
return objects.Where(o => idSelector(o) == id && o.CreatedDate > date);
}
该方法将像这样调用:
var modified = GetNew(dbObjects, id, date, entity => entity.PersonId);
不幸的是,我收到错误:
'idSelector' is a variable but is used like a method.
传递给该方法的表达式应执行以下操作:
objects.Where(o => o.PersonId == id && o.CreatedDate > date);
您需要构建一个表示条件的新表达式并将其传递给Where
:
public static IEnumerable<T> GetNew<TId, T>(IQueryable<T> objects, TId id, DateTime date, Expression<Func<T, TId>> idSelector)
where T : class, ISyncable<TId>
{
var paramExpr = Expression.Parameter(typeof(T));
var idEqExpr = Expression.Equal(Expression.Invoke(idSelector, paramExpr), Expression.Constant(id));
var createdPropExpr = Expression.Property(paramExpr, "CreatedDate");
var gtExpr = Expression.GreaterThan(createdPropExpr, Expression.Constant(date));
var andExpr = Expression.And(idEqExpr, gtExpr);
var condExpr = Expression.Lambda<Func<T, bool>>(andExpr, paramExpr);
return objects.Where(condExpr);
}
编辑:如果您知道idSelector
是属性表达式,则可以提取引用的属性并创建新的属性表达式,而不是使用Invoke
:
var idProperty = (PropertyInfo)((MemberExpression)idSelector.Body).Member;
var idEqExpr = Expression.Equal(Expression.Property(paramExpr, idProperty), Expression.Constant(id));