2011-10-14 100 views
5

我開始瘋狂地試圖理解LINQ中的表達式。任何幫助非常感謝(甚至告訴我,我完全離開這裏)。LINQ中的嵌套泛型Lambdas

比方說,我有三個類

public class Person 
{ 
    public string Name { get; set;} 
    public IEnumerable<PersonLocation> Locations { get; set;} 
    public IEnumerable<PersonEducation> Educations { get; set:} 
} 

public class PersonLocation 
{ 
    public string Name { get; set;} 
    public string Floor { get; set;} 
    public string Extension { get; set;} 
} 

public class PersonEducation 
{ 
    public string SchoolName { get; set;} 
    public string GraduationYear { get; set;} 
} 

我試圖創建一個發生在一個字符串的方法,如Locations.Name或Locations.Floor,或Educations.SchoolName那麼,這將創造一個動態LINQ查詢

IEnumerable<Person> people = GetAllPeople(); 
GetFilteredResults(people, "Location.Name", "San Francisco"); 
GetFilteredResults(people, "Location.Floor", "17"); 
GetFilteredResults(people, "Educations.SchoolName", "Northwestern"); 

GetFilteredResults(IEnumerable<Person> people, string ModelProperty, string Value)方法應該創建大致相當於people.Where(p => p.Locations.Any(pl => pl.Name == Value);

我h的表達AVE這個工作如果ModelProperty是一個字符串,即people.Where(P => p.Name ==值)看起來是這樣的:

string[] modelPropertyParts = ModelProperty.Split('.'); 
var prop = typeof(Person).GetProperty(modelPropertyParts[0]); 
var sourceParam = Expression.Parameter(typeof(Person), "person"); 
var expression = Expression.Equal(Expression.PropertyOrField(sourceParam, modelPropertyParts[0]), Expression.Constant(option.Name)); 
var whereSelector = Expression.Lambda<Func<Person, bool>>(orExp, sourceParam); 
return people.Where(whereSelector.Compile()); 

這就是我一直在擺弄周圍一個IEnumerable的類型,但我就不能得到內的任何,這似乎是正確的,勾搭成外凡:

/*i.e. modelPropertyParts[0] = Locations & modelPropertyParts[1] = Name */ 
string[] modelPropertyParts = ModelProperty.Split('.'); 

var interiorProperty = prop.PropertyType.GetGenericArguments()[0]; 
var interiorParameter = Expression.Parameter(interiorProperty, "personlocation"); 
var interiorField = Expression.PropertyOrField(interiorParameter, modelPropertyParts[1]); 
var interiorExpression = Expression.Equal(interiorField, Expression.Constant(Value)); 
var innerLambda = Expression.Lambda<Func<PersonLocation, bool>>(interiorExpression, interiorParameter); 

var outerParameter = Expression.Parameter(typeof(Person), "person"); 
var outerField = Expression.PropertyOrField(outerParameter, modelPropertyParts[0]); 
var outerExpression = ?? 
var outerLambda == ?? 

return people.Where(outerLambda.Compile()); 

回答

1

的問題是,System.Linq.Enumerable.Any是一個靜態擴展方法。

outerExpression必須引用System.Linq.Enumerable.Any(IEnumerable<T>, Func<T, bool>)

var outerExpression = Expression.Call(
    typeof(System.Linq.Enumerable), 
    "Any", 
    new Type[] { outerField.Type, innerLambda.Type }, 
    outerField, innerLambda); 

這些鏈接,瞭解更多信息,請看:

+0

太棒了,謝謝!這基本上工作,唯一的問題是你傳入的類型是不正確的。它應該是interiorProperty而不是typeof(Person) –

+0

噢,我現在看到了。隨意更正答案(社區wiki) –