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

c# entity-framework expression-trees linq

Question

I'm developing a helper function that produces an expression based on a property that may be used in a linq to entities operation's orderby, where, etc.

I have defined the property as object and dynamic since I won't know its type up front, and I've also attempted to utilizeExpression.Convert But it won't work for properties that aren't of the string type.

The property type I'm dealing with right now that isn't a string isint? and the flaw I encounter 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 previously said, I used both object and dynamic in the line above with the same outcomes. Additionally, I attempted to convert it to the appropriate type, but it didn't work:

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

I test this when I'm in debug mode.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 do an order-by, I receive

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

I reasoned that maybe I should create the Expression dynamically. Lambda is using the appropriate type when I check it, but I haven't yet done that.

Thank you for any assistance.

1
1
11/13/2016 10:34:28 AM

Popular Answer

Make it into an object by

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

Returning that ought to be OK, but you'll have to handle these converters on the other side, when you do the Orderby, first.

    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});
}
1
11/13/2016 9:19:44 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow