Próbuję utworzyć wyrażenie lambda, które zostanie połączone z innymi w dość dużym drzewie wyrażeń do filtrowania. Działa to dobrze, dopóki nie będę musiał filtrować według właściwości kolekcji podrzędnej.Budowanie drzewa ekspresji dynamicznej w celu filtrowania właściwości kolekcji
Jak zbudować wyrażenie Lambda, które będzie filtrować przy użyciu Any() na właściwości kolekcji, która jest właściwością obiektu głównego?
Przykład:
CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test"))
ten sposób chciałbym zbudować wyrażenie statycznie, ale trzeba ją zbudować dynamicznie. Przepraszam za zamieszanie.
Edycja: Oto fragment o tym, jak poradzić sobie z mniej skomplikowanych wyrażeń:
IQueryable<Office> officeQuery = CurrentDataSource.Offices.AsQueryable<Office>();
ParameterExpression pe = Expression.Parameter(typeof(Office), "Office");
ParameterExpression tpe = Expression.Parameter(typeof(Trades), "Trades");
Expression SimpleWhere = null;
Expression ComplexWhere = null;
foreach (ServerSideFilterObject fo in ssfo)
{
SimpleWhere = null;
foreach (String value in fo.FilterValues)
{
if (!CollectionProperties.Contains(fo.PropertyName))
{
//Handle singleton lambda logic here.
Expression left = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName));
Expression right = Expression.Constant(value);
if (SimpleWhere == null)
{
SimpleWhere = Expression.Equal(left, right);
}
else
{
Expression e1 = Expression.Equal(left, right);
SimpleWhere = Expression.Or(SimpleWhere, e1);
}
}
else
{
//handle inner Collection lambda logic here.
Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name"));
Expression right = Expression.Constant(value);
Expression InnerLambda = Expression.Equal(left, right);
//Problem area.
Expression OfficeAndProperty = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName));
Expression OuterLambda = Expression.Call(OfficeAndProperty, typeof(Trades).GetMethod("Any", new Type[] { typeof(Expression) }),InnerLambda);
if (SimpleWhere == null)
SimpleWhere = OuterLambda;
else
SimpleWhere = Expression.Or(SimpleWhere, OuterLambda);
}
}
if (ComplexWhere == null)
ComplexWhere = SimpleWhere;
else
ComplexWhere = Expression.And(ComplexWhere, SimpleWhere);
}
MethodCallExpression whereCallExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { officeQuery.ElementType }, officeQuery.Expression, Expression.Lambda<Func<Office, bool>>(ComplexWhere, new ParameterExpression[] { pe }));
results = officeQuery.Provider.CreateQuery<Office>(whereCallExpression);
Czy pytasz, jak zbudować drzewo wyrażeń? – SLaks
Nie jestem pewien, jak działa hierarchia w twoim przykładzie. Czy możesz rozwinąć trochę więcej na ten temat? Czy urzędy są korzeniami, a następnie każdy Urząd ma kolekcję Transakcji? A chcesz filtrować nazwę handlu? Filtr jest tam, gdzie jestem trochę zagubiony. Przepraszam. –
Nie, po prostu nie jestem pewien składni używanej do budowania wyrażenia z wewnętrznym wywołaniem metody i wyrażeniem dla parametru. W tym przypadku otrzymuję komunikat o błędzie stwierdzający, że nie można znaleźć Any(), ponieważ moje parametry nie pasują do definicji. W tym przypadku nie jestem pewien, czy to dlatego, że jestem wyłączony na składni lub jeśli Any() nie jest obsługiwany w sposób, w jaki go używam. – George