2016-07-21 14 views
2

Vielleicht ist das ein doppelter Thread, aber ich werde es versuchen, weil es einen winzigen Unterschied gibt.Einen dynamischen Ausdrucksbaum erstellen, um nach einer Auflistungseigenschaft zu filtern 2

Ich versuche, einen dynamischen Ausdruck zu erstellen, um eine Auflistungseigenschaft zu filtern.

Der Code:

public class TestEntity 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<string> Values { get; set; } 
} 

public class TestFilter 
{ 
    public TestFilter() 
    { 
     var itens = new List<TestEntity>(); 

     itens.Add(new TestEntity { ID = 1, Name = "Test1", Values = new List<string> { "V1", "V2" } }); 
     itens.Add(new TestEntity { ID = 2, Name = "Test2", Values = new List<string> { "V6", "V3" } }); 
     itens.Add(new TestEntity { ID = 3, Name = "Test3", Values = new List<string> { "V4", "V5" } }); 
     itens.Add(new TestEntity { ID = 4, Name = "Test4", Values = new List<string> { "V2", "V3" } }); 

     itens = itens.Where(e => e.Values.Any(c => c.Equals("V2"))).ToList(); 

     **//Result IDs: 1, 4** 
    } 
} 

Der Filter oben gibt mir IDs 1 und 4 als Ergebnis.

Ich möchte Elemente filtern, wo ein bestimmter Wert in der Sammlung "Werte" existiert.

Bisher habe ich versucht this Thread, aber nicht realisiert, wie es gemacht werden kann.

Jede Hilfe würde geschätzt werden.

+0

Also willst du den Ausdruck in 'c => c.Equals (" V2 ")' dynamisch machen? – ckruczek

+0

Ich möchte e => e.Values.Any machen (c => c.Equals ("V2")). Vielen Dank! – marcodotnet

+0

Was erwarten Sie im Ergebnis? –

Antwort

2

Sie suchen also nach einer Methode, die den Namen und den Wert einer Auflistungseigenschaft angibt, so dass Where Prädikat wie e => e.Collection.Any(c => c == value) erzeugt wird.

Sie können das folgende Erweiterungsmethode (hoffen, dass der Code ist selbsterklärend):

public static class QueryableExtensions 
{ 
    public static IQueryable<T> WhereAnyEquals<T>(this IQueryable<T> source, string collectionName, object value) 
    { 
     var e = Expression.Parameter(typeof(T), "e"); 
     var collection = Expression.PropertyOrField(e, collectionName); 
     var itemType = (collection.Type.IsIEnumerableT() ? collection.Type : 
      collection.Type.GetInterfaces().Single(IsIEnumerableT)) 
      .GetGenericArguments()[0]; 
     var c = Expression.Parameter(itemType, "c"); 
     var itemPredicate = Expression.Lambda(
      Expression.Equal(c, Expression.Constant(value)), 
      c); 
     var callAny = Expression.Call(
      typeof(Enumerable), "Any", new Type[] { itemType }, 
      collection, itemPredicate); 
     var predicate = Expression.Lambda<Func<T, bool>>(callAny, e); 
     return source.Where(predicate); 
    } 

    private static bool IsIEnumerableT(this Type type) 
    { 
     return type.IsInterface && type.IsConstructedGenericType && 
      type.GetGenericTypeDefinition() == typeof(IEnumerable<>); 
    } 
} 

wie folgt aus:

itens = itens.AsQueryable().WhereAnyEquals("Values", "V2").ToList(); 

Wenn Sie Schritt durch den Code, die Variable predicate enthält den Ausdruck Sie fragen nach.

+1

Ivan, das ist schön! Ich danke dir sehr! – marcodotnet

+0

Sie sind herzlich willkommen, froh, dass Sie es mögen :) –