2012-09-12 34 views
0

與下面的代碼LINQ查詢,我沒有任何問題進行排序FirstNameLastName 但我希望能夠排序NameCode了。有沒有一種解決方案來排序屬性,這個屬性是一個「複雜的對象」,而不是一個原始的?對財產動態排序依據和複雜的對象

感謝,

我的對象:

public class Person 
{ 
    public Language Language { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

public class Language 
{ 
    public string Name { get; set; } 
    public string Code { get; set; } 
} 

我有這樣的一段代碼進行排序:

var type = typeof(T); 
var property = type.GetProperty("OrderBy"); 
var parameter = Expression.Parameter(type, "p"); 
var propertyAccess = Expression.MakeMemberAccess(parameter, property); 
var orderByExp = Expression.Lambda(propertyAccess, parameter); 
MethodCallExpression resultExp = 
    Expression.Call(typeof(Queryable), 
    "OrderBy", 
    new Type[] { type, property.PropertyType }, 
    source.Expression, 
    Expression.Quote(orderByExp)); 
return source.Provider.CreateQuery<T>(resultExp); 
+1

代碼中沒有子類。名稱和代碼是您的Person類的屬性的屬性。 –

+0

@MaurícioLinhares讓我重述一下......並不是所有的時間都是「語言」對象,但可以是另一種類型。 –

+0

@ Kris-I:請編輯問題的標題,然後 - 我閱讀它也尋找子類。 –

回答

2

有沒有排序的屬性及該物業的解決方案是一個「複雜的對象」而不是一個原始的?

當然 - 你必須從根本上建立表達式樹相當於一個:

data.OrderBy(p => p.Language.Name) 

這兩種基本屬性訪問表達式,在其中一人的「源」是「結果」的另一個。所以你需要把你的屬性字符串(例如「Language.Name」),分成幾個部分,然後迭代各個位,保持當前表達式作爲目標。例如:

Expression parameter = Expression.Parameter(type, "p"); 
Expression target = parameter; 
foreach (string property in propertyParts) 
{ 
    target = Expression.Property(target, property); 
} 
var orderByExp = Expression.Lambda(target, parameter); 
+0

你可以用一個簡單的摺疊替換循環:'target = propertyParts.Aggregate(target,Expression.Property);'。 此外,我想你忘了聲明和分配'參數'。 –

+1

@ThomSmith:修正了參數的聲明,但是我個人會發現'foreach'循環比'Aggregate'調用更容易理解。在所有的LINQ操作符中,我發現'Aggregate'是最不容易使用的一個。我理解這些原則 - 我總是發現,當使用這些原則時,我必須更加努力地思考。很明顯,如果你來自功能性背景,當然可能有幫助... –

+0

YMMV。 'Aggregate'有時會讓我感到不安,可能是因爲微軟決定任意重命名所有LINQ的標準函數操作符,並且二進制'fold'和一元'reduce'被綁在一起。 –