LINQ 表达式树避免内部转换为对象
LINQ Expression tree avoid inner cast to object
有这种表达式 Expression<Func<SampleType, object> sortField = entity => entity.UpdateDate
其中 UpdateDate
是 DateTime
,当我在运行时调试到表达式主体时,表达式被翻译成这样 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");
让我们看看我在做什么。
- 我检查表达式是否是一元表达式(
Convert(entity.UpdateDate)
是一元表达式),如果是,我继续确定表达式的操作数,在您的示例中为 entity.UpdateDate
。
- 我检查这个新表达式是否是一个成员表达式,即试图访问一个成员(一个字段,一个属性,甚至一个方法)(
entity.UpdateDate
是一个成员表达式)
- 如果它不是成员表达式那么我认为整个表达式无效
- 如果是,那么我将获取正在访问的成员,这将是您的
UpdateDate
属性。
- 现在我的 属性 作为
PropertyInfo
比较容易处理。
如果需要的类型是Expression<Func<TEntity, object>>
,那么你不能在没有转换的情况下创建树。要么你的 ORM 必须处理转换(按照@Matias Cicero 的建议),要么你需要传入一个 Expression<Func<TEntity, TProperty>>
,据我所知,这是大多数 ORM 处理它的方式。
有这种表达式 Expression<Func<SampleType, object> sortField = entity => entity.UpdateDate
其中 UpdateDate
是 DateTime
,当我在运行时调试到表达式主体时,表达式被翻译成这样 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");
让我们看看我在做什么。
- 我检查表达式是否是一元表达式(
Convert(entity.UpdateDate)
是一元表达式),如果是,我继续确定表达式的操作数,在您的示例中为entity.UpdateDate
。 - 我检查这个新表达式是否是一个成员表达式,即试图访问一个成员(一个字段,一个属性,甚至一个方法)(
entity.UpdateDate
是一个成员表达式) - 如果它不是成员表达式那么我认为整个表达式无效
- 如果是,那么我将获取正在访问的成员,这将是您的
UpdateDate
属性。 - 现在我的 属性 作为
PropertyInfo
比较容易处理。
如果需要的类型是Expression<Func<TEntity, object>>
,那么你不能在没有转换的情况下创建树。要么你的 ORM 必须处理转换(按照@Matias Cicero 的建议),要么你需要传入一个 Expression<Func<TEntity, TProperty>>
,据我所知,这是大多数 ORM 处理它的方式。