2014-10-30 1 views
1

Я пытаюсь построить построитель предикатов, который возвращает предикат, который проверяет, содержит ли список ints другой список int. До сих пор у меня есть этоСоздайте построитель предикатов для (x => listOfInts.Contains (x.ListOfIntsToCheck))

public static Expression<Func<T, bool>> DynamicIntContains<T, TProperty>(string property, IEnumerable<TProperty> items) 
{ 
    var pe = Expression.Parameter(typeof(T)); 
    var me = Expression.Property(pe, property); 
    var ce = Expression.Constant(items); 
    var call = Expression.Call(typeof(List<int>), typeof(List<int>).GetMethod("Contains").Name, new[] { typeof(int) }, ce, me); 
    return Expression.Lambda<Func<T, bool>>(call, pe); 
} 

T - объект поиска, который содержит список идентификаторов в качестве одного из его свойств. TProperty список Интс и имущества имя списка на ошибки property.The я получаю это

Additional information: No method 'Contains' exists on type 'System.Collections.Generic.List`1[System.Int32]'. 

Является ли это потому, что я называю его из статического метода? Или я пытаюсь получить доступ к методу на typeof (List) некорректно? Благодарю.

+0

Возможный дубликат [Как использовать LINQ Contains (string \ [\]) вместо Contains (string)] (http://stackoverflow.com/questions/194930/how-do-i-use-linq- containsstring-вместо-containsstring) – GSerg

+0

Это вообще не связано с этим вопросом. – Dan

+0

Как насчет этого, @Dan http://stackoverflow.com/questions/16347794/how-to-build-an-ienumerableint-contains-expression – Darek

ответ

1

Вот решение;

public static Expression<Func<T, bool>> DynamicIntContains<T, TProperty>(string property, IEnumerable<TProperty> items, object source, PropertyInfo propertyInfo) 
    { 
     var pe = Expression.Parameter(typeof(T)); 
     var me = Expression.Property(pe, property.Singularise()); 
     var ce = Expression.Constant(propertyInfo.GetValue(source, null), typeof(List<int>)); 
     var convertExpression = Expression.Convert(me, typeof(int)); 
     var call = Expression.Call(ce, "Contains", new Type[] { }, convertExpression); 
     return Expression.Lambda<Func<T, bool>>(call, pe); 
    } 

Это исходит из предположения, что имя списка является множественным числом его членов. В Expression.Call я передавал typeof (List), правильный метод - передать Type []. Представляется также необходимым преобразовать выражение MemberExpression в константу определенного типа. Благодарю.

-2

Здесь вы идете:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var t1 = new List<int> {1, 3, 5}; 
     var t2 = new List<int> {1, 51}; 
     var s = new List<int> {1, 2, 3, 4, 5, 6, 7, 8, 9}; 
     Console.WriteLine(s.Contains(t1)); 
     Console.WriteLine(s.Contains(t2)); 
    } 

} 

public static class Extensions 
{ 
    public static bool Contains(this List<int> source, List<int> target) 
    { 
     return !target.Except(source).Any(); 
    } 
} 

И Generic форма:

public static bool Contains<T>(this List<T> source, List<T> target) 
{ 
    return !target.Except(source).Any(); 
} 

Еще более общий:

public static bool Contains<T>(this IEnumerable<T> source, IEnumerable<T> target) 
{ 
    return !target.Except(source).Any(); 
} 
+0

Это только опция для LINQ для объектов, в то время как вопрос очень четко выражает выражение для использования в поставщике запросов, к которому он будет переведен в SQL или какой-либо другой механизм запросов, не относящийся к C#. – Servy

+0

Ну, вот что я думал, @ Серви, но я могу ошибаться. Список не имеет метода Содержит, который принимает набор. Он принимает только значение типа Т. Интересно, сможет ли он совместить свой код с моим, который предоставляет Contains с IEnumerable . У меня не так много опыта с выражениями, тем не менее, так что это немного выстрел в темноте. – Darek

+0

Это не имеет никакого отношения к вопросу, касающемуся построения предикатов. @Servy в точности прав. – Dan