2016-04-06 5 views
1

Как говорится в названии, я пытаюсь создать дерево выражений для cheking, если какой-либо элемент в списке строки соответствуют строке объекта Book.Создание дерева выражений для List.Any (v => v.Contains (Book.Title.ToString()))

До сих пор я получил это:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
    { 
     var parameter = Expression.Parameter(typeof(Books), "b"); 
     var listParameter = Expression.Parameter(typeof(string), "v"); 
     var property = Expression.Property(parameter, propertyName); 
     var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
     var toStringMethod = typeof(object).GetMethod("ToString"); 
     var containsMethod = typeof(string).GetMethod("Contains"); 
     var objectString = Expression.Call(property, toStringMethod); 
     var lambda = Expression.Call(listParameter, containsMethod, objectString); 
     var func = Expression.Lambda<Func<List<string>, bool>>(lambda, parameter); 
     var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

     return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
    } 

Но я получаю эту ошибку:

Expression of type 'System.Boolean' cannot be used for parameter of type 'System.Func 2[System.String,System.Boolean]' of method 'Boolean Any[String](System.Collections.Generic.IEnumerable 1[System.String], System.Func`2[System.String,System.Boolean])'

На этой линии:

var comparison = Expression.Call(anyMethod, Expression.Constant(values), lambda); 

Я чувствую, что я просто нужен последний маленький бит.

Заранее спасибо :-)

EDIT: Для разъяснения. Я объясню немного более подробное, что мне нужно.

Мне нужно было классифицировать книги на основе некоторых свойств книг. В этом конкретном случае я передаю список строк функции. Мне нужно было проверить, содержалась ли какая-либо из этих строк в любом названии книг.

Итак, прежде всего, лямбда, с которой я считала нужным, была неправильной для начала. Это лямбда, что я на самом деле необходимое: b => values.Any(v => b.Title.ToString().Contains(v))

И вот окончательный код, который я закончил с:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
    { 
     var parameter = Expression.Parameter(typeof(Books), "b"); 
     var listParameter = Expression.Parameter(typeof(string), "v"); 
     var property = Expression.Property(parameter, propertyName); 
     var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
     var toStringMethod = typeof(object).GetMethod("ToString"); 
     var containsMethod = typeof(string).GetMethod("Contains"); 
     var objectString = Expression.Call(property, toStringMethod); 
     var lambda = Expression.Call(objectString, containsMethod, listParameter); 
     var func = Expression.Lambda<Func<string, bool>>(lambda, listParameter); 
     var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

     return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
    } 
+0

Ваш func, вероятно, не такой, как вы думаете, и, вероятно, прищурился. Любой метод расширения, поэтому вам нужно будет вызвать статический метод в своем выражении. Список должен быть списком книг? Похоже, это так, но, похоже, вы рассматриваете аргумент для функции Any func как самого списка, а не одну из книг в списке. Все выглядит неправильно ... Я думаю, что есть конвертер выражения ambda =>, который вы можете использовать, чтобы узнать, как работает материал ... lemme peek для него. – Will

+0

Да, я думаю, вы можете просто пойти 'Expression > expr = x => x.Any (v => v.Contains (Book.Title.ToString())) ;; а затем изучить выражение в быстрой посмотреть окно, чтобы посмотреть, как оно построено. Опять же, я не знаю, что ваш «TInput» от лямбды в вашем названии. – Will

+0

Я отредактировал сообщение, чтобы вы могли увидеть полный метод. –

ответ

1

Заключительный рабочий код:

private static Expression<Func<Books, bool>> GenerateListContainsLikeExpression(string propertyName, List<string> values) 
{ 
    var parameter = Expression.Parameter(typeof(Books), "b"); 
    var listParameter = Expression.Parameter(typeof(string), "v"); 
    var property = Expression.Property(parameter, propertyName); 
    var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).First(m => m.Name == "Any" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(string)); 
    var toStringMethod = typeof(object).GetMethod("ToString"); 
    var containsMethod = typeof(string).GetMethod("Contains"); 
    var objectString = Expression.Call(property, toStringMethod); 
    var lambda = Expression.Call(objectString, containsMethod, listParameter); 
    var func = Expression.Lambda<Func<string, bool>>(lambda, listParameter); 
    var comparison = Expression.Call(anyMethod, Expression.Constant(values), func); 

    return Expression.Lambda<Func<Books, bool>>(comparison, parameter); 
} 

Для более глубокого объяснения проблема. См. Мое редактирование в исходном сообщении.