在这个场景中我需要"by pass"将OrderBy
表达式转换为嵌套属性,但我不能简单地更改表达式,因为它在太多地方使用而不涉及嵌套属性。
例如,我有这两个用于生成IQueryable<Parent>
的类,并且使用.OrderBy("Title DESC")
应用顺序,等等。然而,"Title DESC"
表达式是由外部世界提供的,这使得重构非常困难。
class Parent {
public Nested NestedProp {get;set;}
/* other irrelevant props */
}
class Nested {
public string Id {get;set;}
public string Title {get;set;}
public DateTime CreatedAt {get;set;}
/* other irrelevant props */
}
我通过如下方法恢复它:
public IQueryable<Parent> GetParentsOrdered(stirng order){
IQueryable<Parent> query = QueryParents();
return query.OrderBy(order);
}
用法如下:
var listOfParents = GetParentsOrdered("Title DESC");
问题是,为了使其正常工作,我必须考虑到按表达式排序的NestedProp
,这将需要在我不完全控制的源代码中进行太多重构,只是为了使排序立即工作。
的例子:
var listOfParents = GetParentsOrdered("Nested.Title DESC");
问题是,有没有办法告诉动态Linq用NestedProp
作为表达式的前缀,这样我就可以通过直接在表达式上提供子属性并将排序直接传递给NestedProp
来进行排序?
像这样:
query.OrderByPrefixed("NestedProp", "Title DESC, CreatedAt DESC");
下面是一些使用反射自动为嵌套属性名添加前缀的代码。可以进行扩展以自动提取(多个)嵌套属性。这段代码假设Parent
和Nested
之间的属性名没有重叠。
static List<string> NestedPropertyNames = typeof(Nested).GetProperties().Select(pi => pi.Name).ToList();
static Regex srcPattern = new Regex(@"(?<=W|^)(?:"+String.Join("|", NestedPropertyNames)+@")(?=W|$)", RegexOptions.Compiled);
public IQueryable<Parent> GetParentsOrdered(string order){
IQueryable<Parent> query = QueryParents();
return query.OrderBy(srcPattern.Replace(order, "NestedProp.$&"));
}