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

时间:2015-10-30 11:59:30

标签: c# linq lambda expression-trees

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

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

那么,有没有办法避免这种内心演员?

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

2 个答案:

答案 0 :(得分:2)

我记得很久以前在一个项目上遇到同样的问题。

如果您有权访问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. 我检查这个新表达式是否是 成员表达式 ,即尝试访问成员(字段,属性,甚至方法)({{ 1}}是一个成员表达式)
  3. 如果它不是 成员表达式 ,那么我认为整个表达式无效
  4. 如果是,那么我会访问该成员,这将是您案例中的entity.UpdateDate属性。
  5. 现在我的财产为UpdateDate,相对容易处理。

答案 1 :(得分:1)

如果所需类型为Expression<Func<TEntity, object>>,则无法在没有强制转换的情况下创建树。您的ORM必须处理演员阵容(正如@Matias Cicero建议的那样),或者您需要传入Expression<Func<TEntity, TProperty>>,这就是大多数ORM处理它的方式。据我所知。