首页 > 解决方案 > 使用 linq 动态排序集合导航属性

问题描述

我正在尝试根据属性对集合进行排序。

所以我直到运行时才知道要排序的属性。

以下适用于主要对象但不适用于任何子对象

var prop = TypeDescriptor.GetProperties(typeof(TvRequests)).Find(sortProperty, tru

if (sortProperty.Contains('.'))
{
    // This is a navigation property currently not supported
    prop = TypeDescriptor.GetProperties(typeof(TvRequests)).Find("Title", true);
}
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
    ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
    : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();

所以 thesortProperty被传递到我的方法中并且是一个字符串,可以是类似titleor的东西date,它可以工作。但是,如果我尝试访问我的TvRequests对象的子属性,它将不起作用,例如requestedUser.username

这是我在这个问题中所指的对象的精简版本:

public class TvRequests
{
    public string Title { get; set; }
    [ForeignKey(nameof(RequestedUserId))]
    public OmbiUser RequestedUser { get; set; }
}

public class OmbiUser
{
    public string Username;
}

我的问题是我如何能够动态访问上述任何子属性?

标签: c#.net.net-core

解决方案


使用EF.Property

// Get the string name of the property here
string propertyName = "Title";
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
    ? allRequests.OrderBy(x => EF.Property<string>(x, propertyName)).ToList()
    : allRequests.OrderByDescending(x => EF.Property<string>(x, propertyName)).ToList();

类似的东西可能会起作用(未经测试,但可以编译)

// static for caching & performance 
static private MethodInfo efPropertyGenericMethod = typeof(EF).GetTypeInfo().GetDeclaredMethod("Property");

Expression SortBy<TEntity>(Type type, string propertyName)
{
    var xParam = Expression.Parameter(typeof(TEntity), "x");

    // set T generic type here for EF.Property<T>
    var efPropertyMethod = efPropertyGenericMethod.MakeGenericMethod(type);
    // Creates a Lambda
    Expression lambda = Expression.Lambda(
        // Calls a method. First parameter is null for static calls
        Expression.Call(null,
            efPropertyMethod, // our cosntructed generic Version of EF.Property<T>
            xParam, // Pass the x Parameter
            Expression.Constant(propertyName, typeof(string)) // the propertyName asconstant
        ),
        xParam
    );

    return lambda;
};

用作

allRequests.OrderBy(SortBy<TvRequests>(propertyType, propertyName))

请注意,这SortBy不是在 lambda 中调用的。下面是错误的(x =>上面的行中没有)。

allRequests.OrderBy(x => SortBy<TvRequests>(propertyType, propertyName))

它能做什么?SortBy 生成等效于 的表达式树x => EF.Property<T>(x, "MyPropertyName")

编辑:

更新了方法,所以 x 也被传递给EF.Property(x, propertyName)


推荐阅读