2015-07-06 3 views
1

Использование LINQ Выражение динамического вызова вызывает вызов метода Count().LINQ Dynamic Expression Вызов метода Count() для свойства List

public class Foo 
{ 
     public int Id { get; set; } 
} 

public class Bar 
{ 
     public ICollection<Foo> Data { get; set; } 
} 

var list = new List<Bar>(); 

нужно построить предикат динамически, который может вернуть мне список адвокатов, которые имеют Data.Count()> 1 с помощью выражений.

Чтобы начать что-то вроде этого ..

MethodInfo method = typeof(Enumerable).GetMethods() 
.Where(m => m.Name == "Count" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(Bar)); 
+0

Зачем вам нужно создавать его динамически? Вся необходимая информация известна во время компиляции; просто используйте лямбду. – Servy

+1

@Servy есть возможность создать его динамически –

+0

@ JonahPereira вы можете уточнить? По какой причине вы не могли передать объект IEnumerable ? – Jacob

ответ

2

Count метод, который вы ищете имеет только один параметр:

public static int Count<TSource>(this IEnumerable<TSource> source) 

Вы также можете использовать Count свойство, поскольку источником является ICollection:

//build a lambda: (Bar bar) => bar.Data.Count > 1; 
var barParam = Expression.Parameter(typeof (Bar), "bar"); 
var barDataProperty = Expression.PropertyOrField(barParam, "Data"); 
//since Data is of type ICollection, we can use the Count Property 
var count = Expression.PropertyOrField(barDataProperty, "Count"); 
//if you do not want this dependency, call the Count() extension method: 
var enumerableCountMethod = typeof (Enumerable).GetMethods() 
    .First(method => method.Name == "Count" && method.GetParameters().Length == 1) 
    .MakeGenericMethod(typeof(Foo)); 
var count2 = Expression.Call(enumerableCountMethod, barDataProperty); 

var comparison = Expression.GreaterThan(count, Expression.Constant(1)); 
var comparison2 = Expression.GreaterThan(count2, Expression.Constant(1)); 

Expression<Func<Bar, bool>> expr = Expression.Lambda<Func<Bar, bool>>(comparison, barParam); 
Expression<Func<Bar, bool>> expr2 = Expression.Lambda<Func<Bar, bool>>(comparison2, barParam); 

var list = new List<Bar>(); 
var filteredList = list.Where(expr.Compile()); 
var filteredList2 = list.Where(expr2.Compile()); 
-1

Возможно, вы можете использовать predicate builder. Например:

IQueryable<Product> SearchProducts (params string[] keywords) 
{ 
    var predicate = PredicateBuilder.False<Product>(); 

    foreach (string keyword in keywords) 
    { 
    string temp = keyword; 
    predicate = predicate.Or (p => p.Description.Contains (temp)); 
    } 
    return dataContext.Products.Where (predicate); 
}