Can't build lambda Expression with unknown type of a property

旧街凉风 提交于 2019-12-11 05:37:49

问题


I am building a helper method that returns an expression based on a property that could be used in an orderby or where, etc. in a linq to entities operation.

I won't know the type of the property upfront, so I have declared it as object and dynamic and have also tried to use Expression.Convert but it will not work for non string typed properties.

The current property type that is not a string that I'm working with is int? and the error I get is

Expression of type 'System.Nullable`1[System.Int32]' cannot be used for return type 'System.Object';

Code:

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

AS I said, I've used object and dynamic in line above with same results. I've also tried to convert it to the right type but that doesn't work:

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

While I'm in debug mode and I try this, Expression.Lambda(conversiona, param), it seems to work

{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]]"}

...but when I use it in an orderby I get

error CS1503: Argument 2: cannot convert from 'System.Linq.Expressions.LambdaExpression' to 'string'

I thought that maybe I needed to dynamically build the Expression.Lambda using the correct type as I inspect it but haven't tried that yet

Thanks for any help


回答1:


Convert it to object by

Expression conversion = Expression.Convert(propExp, typeof(object))

That should be ok to be returned, but then you will have to deal with these converts on the other side, where you do the 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});
}


来源:https://stackoverflow.com/questions/40565859/cant-build-lambda-expression-with-unknown-type-of-a-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!