2016-04-06 30 views
1

Başlığın belirttiği gibi, bir listenin herhangi bir öğesi varsa, cheking için bir İfade ağacı oluşturmaya çalışıyorum Dizeler, bir Kitap nesnesinin bir dizesiyle eşleşir.List.Any için İfade Ağacı Oluşturma (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); 
    } 

Ama bu hatayı alıyorum: Bu hatta

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])'

:

Şimdiye kadar bu var Hissederim

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

sadece Son ufaklığa ihtiyacım var.

DÜZENLEME :-) önceden

Teşekkür: açıklama için. İhtiyacım olanı biraz daha ayrıntılı olarak açıklayacağım.

Bazı kitap özelliklerini temel alarak kitapları kategorilere ayırmam gerekiyordu. Bu özel durumda, fonksiyona dizelerin bir listesini iletiyorum. Bu dizelerden herhangi birinin herhangi bir kitapta yer aldığını kontrol etmem gerekiyordu.

Her şeyden önce, ihtiyacım olduğunu düşündüğüm lambda ile başlamak yanlıştı. Bu aslında gerekli lambda geçerli: b => values.Any(v => b.Title.ToString().Contains(v))

Ve burada ile sona erdi nihai kodudur: derinliği açıklamasında daha İçin

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

:

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

Fonksiyonunuz muhtemelen sizin düşündüğünüz şey değildir ve muhtemelen berbattır. Herhangi bir uzantı yöntemidir, bu yüzden İfadenizdeki statik yöntemi çağırmanız gerekir. List, Kitapların bir listesi mi olmalı? Öyle görünüyor, ama listede bir kitap değil, bir listenin kendisi olmak için Any func argümanını ele aldığınız görülüyor. Her şey yanlış görünüyor ... Bence şeyler nasıl çalıştığını öğrenmek için kullanabileceğiniz bir lambda => ifade dönüştürücü var ... bunun için lemme peek. – Will

+0

Evet, bence "Expression > expr = x => x.Any (v => v.Contains (Book.Title.ToString()));' ve sonra ifadeyi hızlıca inceleyebilirsiniz. nasıl yapıldığını görmek için pencereyi izleyin. Yine, senin "TInput" ununun senin başlığındaki lambdadan ne olduğunu bilmiyorum. – Will

+0

Yayını düzenledim, böylece tam yöntemi görebilirsiniz. –

cevap

1

Final çalışma kodu sorun. Orijinal yayındaki düzenlemeye bakın.

İlgili konular