Gebäude einen dynamischen Ausdruck Baum, um filter auf eine "collection" - Eigenschaft
Ich versuche zu bauen, ein lambda-Ausdruck, wird in Kombination mit anderen in einem ziemlich großen Ausdruck Baum für die Filterung. Dies funktioniert gut, bis ich brauche, um filter mit einem sub-collection-Eigenschaft.
Wie bauen Sie einen Lambda-Ausdruck, der filter mit Alle() auf eine Eigenschaft eine Sammlung ist eine Eigenschaft des root-Objekts?
Beispiel:
CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test"))
Dies ist, wie ich bauen würde, die expression statisch, aber ich brauche, um es zu bauen dynamisch. Sorry für die Verwirrung.
Edit: Hier ist ein snippet, wie ich mit dem weniger kompliziert Ausdrücken:
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);
- Du fragst, wie man ein expression tree?
- Ich bin mir nicht sicher, wie die Hierarchie funktioniert in deinem Beispiel. Können Sie näher erläutern, ein wenig mehr? Ist Büros der Wurzel und dann jedes Büro hat eine Sammlung von Trades? Und Sie filtern möchten, auf den Namen des Handels?? Der filter ist, wo ich bin ein wenig verloren. Sorry.
- Nein, ich bin nur nicht sicher über die syntax verwendet, um einen Ausdruck zu erstellen mit einem internen Methodenaufruf und ein Ausdruck für einen parameter. In diesem Fall ist, erhalte ich eine Fehlermeldung, die besagt, dass Jede() kann nicht gefunden werden, weil meine Parameter nicht mit der definition. In diesem Fall bin ich nicht sicher, ob das ist, weil ich mich auf den Weg auf die syntax oder wenn vorhanden() nicht unterstützt, so wie ich bin, es zu benutzen.
- Soweit der Hierarchie: Büros ist die Wurzel, und jedes Büro hat eine Sammlung von trades. Ich bin versucht zu filtern die Sammlung basierend auf den Name-Eigenschaft der einzelnen trades Objekt in der Sammlung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Lösung gefunden. Ich war nicht auf der Suche für jede Methode an der richtigen Stelle vor.
Bitte tun Sie das nicht, was Sie wirklich wollen, es zu benutzen, eine Bibliothek, das sogenannte dynamische linq. http://nuget.org/packages/DynamicLINQ
Können Sie einfach speichern Sie Ihre Abfragen als strings, und es unterstützt sehr komplexe Abfragen. Ausdruck Bäume sind ein Albtraum.
myIQueryable.OrderBy(x => x.MyCollection.Select(y => y.Myproperty))
ich zumindest kann es nicht funktionierenWas du aufgelistet, wie dein Beispiel wird die Arbeit basiert auf Ihrem Kommentar. Hier ist ein Beispiel was ich mit der Arbeit:
Wir haben Vorlagen für bestimmte Sammlung von Feldern und diese Felder benötigt werden könnten. So kann ich die templates, in denen jedes Feld ist erforderlich, dass durch die Erklärung oben.
Hoffentlich hilft...oder zumindest bestätigt, was Sie zu tun versuchen. Lassen Sie mich wissen, wenn Sie haben mehr Fragen zu diesem Thema und ich werde erarbeiten.
Glück!
Den code
sollte funktionieren, solange
o.base_Trades
implementiertIEnumerable<Trade>
. Wenno.base_Trades
nur umsetzenIEnumerable
verwenden, benötigen Sie entwederCast<Trade>()
wenn Sie sicher sein können, dass alle Elemente ino.base_Trades
sind IhreTrade
geben oderOfType<Trade>()
ob es möglicherweise Elemente, die andere (inkompatible) Typen.Dass würde dann so Aussehen: