无法使用未知类型的属性构建Lambda表达式 [英] Can't build lambda Expression with unknown type of a property

查看:152
本文介绍了无法使用未知类型的属性构建Lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

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.

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

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

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

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

代码:

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

正如我所说,我在上面使用object和dynamic取得了相同的结果.我也尝试过将其转换为正确的类型,但这是行不通的:

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)

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

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

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

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

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

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

感谢您的帮助

推荐答案

通过

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

应该可以退货,但随后您将不得不在另一侧(由Orderby处理)处理这些转换.

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});
}

这篇关于无法使用未知类型的属性构建Lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆