Access nested properties with dynamic lambda using Linq.Expression

前端 未结 4 2455
说谎
说谎 2021-02-20 10:39

Let\'s assume that I have two classes:

class person
{
    int ID
    string name
    Address address
}
class address
{
    int ID
    string street
    string co         


        
相关标签:
4条回答
  • 2021-02-20 11:22

    Try this one

        public static IQueryable<T> SortIQueryable<T>(IQueryable<T> data, string fieldName, string sortOrder)
        {
            if (string.IsNullOrWhiteSpace(fieldName)) return data;
            if (string.IsNullOrWhiteSpace(sortOrder)) return data;
    
            var param = Expression.Parameter(typeof(T), "i");
    
            MemberExpression property = null;
            string[] fieldNames = fieldName.Split('.');
            foreach (string filed in fieldNames)
            {
                if (property == null)
                {
                    property = Expression.Property(param, filed);
                }
                else
                {
                    property = Expression.Property(property, filed);
                }
            }
    
            Expression conversion = Expression.Convert(property, typeof(object));//Expression.Property(param, fieldName)
            var mySortExpression = Expression.Lambda<Func<T, object>>(conversion, param);
    
            return (sortOrder == "desc") ? data.OrderByDescending(mySortExpression)
                : data.OrderBy(mySortExpression);
        }
    
    0 讨论(0)
  • 2021-02-20 11:25

    It seems to me you're trying to rewrite Microsoft DynamicQuery. Why not just use that instead?

    Here's an example:

    IQueryable<Foo> myQuery = GetHibernateQuery();
    myQuery = myQuery.OrderBy("address.street");
    
    0 讨论(0)
  • 2021-02-20 11:30

    What is not clear?

    You have to split it and then use:

    Expression.Property(Expression.Property(param, "address"), "street")
    
    0 讨论(0)
  • 2021-02-20 11:32

    Here's a more generic version of LukLed's answer:

        protected MemberExpression NestedExpressionProperty(Expression expression, string propertyName)
        {
            string[] parts = propertyName.Split('.');
            int partsL = parts.Length;
    
            return (partsL > 1) 
                ? 
                Expression.Property( 
                    NestedExpressionProperty(
                        expression, 
                        parts.Take(partsL - 1)
                            .Aggregate((a, i) => a + "." + i)
                    ), 
                    parts[partsL - 1]) 
                :
                Expression.Property(expression, propertyName);
        }
    

    You can use it like this:

    var paramExpression = Expression.Parameter(this.type, "val");
    var firstProp = NestedExpressionProperty(paramExpression,"address.street");
    
    0 讨论(0)
提交回复
热议问题