LINQ 表达式树避免内部转换为对象

LINQ Expression tree avoid inner cast to object

有这种表达式 Expression<Func<SampleType, object> sortField = entity => entity.UpdateDate 其中 UpdateDateDateTime,当我在运行时调试到表达式主体时,表达式被翻译成这样 Convert(entity.UpdateDate)将其转换为 System.Object,这是通常的机制。

我的问题与支持 LINQ 排序字段但无法理解 Convert 的 ORM 驱动程序有关。

那么,有没有办法避免这种内部转换?

(驱动程序必须以Expression<Func<TEntity, object>>类型传递)

我记得以前在一个项目中遇到过同样的问题。

如果您可以访问您的 ORM 源​​代码,并且可以修改它, 我想这是我解析表达式的方式:

Expression body = sortExpression;

if (body is UnaryExpression) body = ((UnaryExpression)body).Operand;
if (!(body is MemberExpression)) throw new ArgumentException("Sort expression is invalid");

PropertyInfo property = ((MemberExpression)body).Member as PropertyInfo;
if (property == null) throw new ArgumentException("Sort expression must always be a property access");

让我们看看我在做什么。

  1. 我检查表达式是否是一元表达式Convert(entity.UpdateDate)是一元表达式),如果是,我继续确定表达式的操作数,在您的示例中为 entity.UpdateDate
  2. 我检查这个新表达式是否是一个成员表达式,即试图访问一个成员(一个字段,一个属性,甚至一个方法)(entity.UpdateDate是一个成员表达式)
  3. 如果它不是成员表达式那么我认为整个表达式无效
  4. 如果是,那么我将获取正在访问的成员,这将是您的 UpdateDate 属性。
  5. 现在我的 属性 作为 PropertyInfo 比较容易处理。

如果需要的类型是Expression<Func<TEntity, object>>,那么你不能在没有转换的情况下创建树。要么你的 ORM 必须处理转换(按照@Matias Cicero 的建议),要么你需要传入一个 Expression<Func<TEntity, TProperty>>,据我所知,这是大多数 ORM 处理它的方式。