2016-07-21 5 views
2

多分これは重複したスレッドですが、少し違いがあるので試してみるつもりです。コレクションプロパティをフィルタリングするための動的な式ツリーの構築2

私は、コレクションプロパティをフィルタリングするために動的な式を構築しようとしています。

コード:

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** 
    } 
} 

上記フィルタは、結果としてのIDを私1,4を与えます。

コレクション「値」に特定の値が存在するエンティティをフィルタ処理したいとします。

これまでのところ、私はthisスレッドを試しましたが、どのように実行できるのか分かりませんでした。

助けが必要です。

+0

だから、 'c => c.Equals(" V2 ")'の式を動的にしたいのですか? – ckruczek

+0

私はe => e.Values.Any(c => c.Equals( "V2"))を作りたいと思っています。ありがとうございました! – marcodotnet

+0

あなたは結果で何を期待していますか? –

答えて

2

したがって、コレクションプロパティ名と値を指定するとWhere述語(e => e.Collection.Any(c => c == value)など)が生成されるメソッドを探しています。

あなたは(コードは自明であると思います)、次の拡張メソッドを使用することができます。このような

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<>); 
    } 
} 

:あなたがコードをステップ実行した場合

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

、変数predicateは表現が含まれていますあなたは求めています。

+1

イワン、それは美しいです!どうもありがとうございます! – marcodotnet

+0

あなたはそれが好き嬉しくて嬉しいです:) –