无法使用未知类型的属性

时间:2016-11-12 17:49:43

标签: c# entity-framework linq expression-trees

我正在构建一个帮助器方法,该方法返回一个基于属性的表达式,该属性可以在linq到实体操作中的orderby或where等中使用。

我不会事先了解该属性的类型,因此我已将其声明为对象和动态,并且还尝试使用Expression.Convert,但它不适用于非字符串类型的属性。

当前属性类型不是我正在使用的字符串int?,我得到的错误是

  

类型'System.Nullable`1 [System.Int32]'的表达式不能用于返回类型'System.Object';

代码:

var param = Expression.Parameter(typeof(Employee), "x");
MemberExpression propExp = Expression.Property(param, "somePropertyName");
Expression.Lambda<Func<Employee, object>>(propExpression, param);

正如我所说,我在上面使用了对象和动态,结果相同。我也尝试将其转换为正确的类型但不起作用:

Expression conversion = Expression.Convert(propExp, ((PropertyInfo)propExp.Member).PropertyType)

当我处于调试模式时,我尝试了这个Expression.Lambda(conversiona, param),它似乎可以正常工作

{x => Convert(x.EmployeeNo)}
Body: {Convert(x.EmployeeNo)}
CanReduce: false
DebugView: ".Lambda #Lambda1<System.Func`2[xx.DomainModel.Entities.Employee,System.Nullable`1[System.Int32]]>(xx.DomainModel.Entities.Employee $x)\r\n{\r\n    (System.Nullable`1[System.Int32])$x.EmployeeNo\r\n}"
Name: null
NodeType: Lambda
Parameters: Count = 1
ReturnType: {Name = "Nullable`1" FullName = "System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}
TailCall: false
Type: {Name = "Func`2" FullName = "System.Func`2[[xx.DomainModel.Entities.Employee, Fng.Facts.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

...但是当我按顺序使用它时,我得到了

  

错误CS1503:参数2:无法从'System.Linq.Expressions.LambdaExpression'转换为'string'

我想也许我需要使用正确的类型动态构建Expression.Lambda,因为我检查它但尚未尝试过

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

通过

将其转换为对象
Expression conversion = Expression.Convert(propExp, typeof(object))

这应该可以归还,但是你必须在另一边处理这些转换,你可以在那里处理Orderby。

    private IQueryable<T> AddOrderBy<T>(IQueryable<T> query, Expression<Func<T, object>> orderByProperty, bool isAscending, bool isFirst)
{
    Expression<Func<IOrderedQueryable<int>, IQueryable<int>>> methodDef = isAscending 
        ? (isFirst ? (Expression<Func<IOrderedQueryable<int>, IQueryable<int>>>)(q => q.OrderBy(x => x)) : (Expression<Func<IOrderedQueryable<int>, IQueryable<int>>>)(q => q.ThenBy(x => x)))
        : (isFirst ? (Expression<Func<IOrderedQueryable<int>, IQueryable<int>>>)(q => q.OrderByDescending(x => x)) : (Expression<Func<IOrderedQueryable<int>, IQueryable<int>>>)(q => q.ThenByDescending(x => x)));

    // get the property type
    var propExpression = orderByProperty.Body.NodeType == ExpressionType.Convert && orderByProperty.Body.Type == typeof(object)
        ? (LambdaExpression)Expression.Lambda(((UnaryExpression)orderByProperty.Body).Operand, orderByProperty.Parameters)
        : orderByProperty;

    var methodInfo = ((MethodCallExpression)methodDef.Body).Method.GetGenericMethodDefinition().MakeGenericMethod(typeof(T), propExpression.Body.Type);
    return (IQueryable<T>)methodInfo.Invoke(null, new object[]{query, propExpression});
}