【问题标题】:Create a predicate builder for (x => listOfInts.Contains(x.ListOfIntsToCheck))为 (x => listOfInts.Contains(x.ListOfIntsToCheck)) 创建一个谓词构建器
【发布时间】:2014-10-30 17:41:28
【问题描述】:

我正在尝试构建一个谓词构建器,它返回一个谓词,该谓词检查一个整数列表是否包含另一个整数列表。到目前为止我有这个

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 是搜索对象,它包含一个 ID 列表作为它的属性之一。 TProperty 是整数列表,属性是属性列表的名称。我得到的错误是

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

这是因为我是从静态方法调用它吗?还是我试图错误地访问 typeof(List) 上的方法?谢谢。

【问题讨论】:

标签: c# linq reflection predicates


【解决方案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();
        }
    }
    

    还有一个通用形式:

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

    【讨论】:

    • 这只是 LINQ to objects 的一个选项,而问题很明显是构建一个用于查询提供程序的表达式,它将被转换为 SQL 或其他一些非 C# 查询机制.
    • 嗯,这就是我的想法,@Servy,但我可能错了。 List 没有可以接受集合的方法 Contains。它只接受 T 类型的值。我想知道他是否能够将他的代码与我的代码结合起来,这提供了包含 IEnumerable 的代码。我还没有太多的表情经验,所以有点摸不着头脑。
    • 这与问题无关,是关于构建谓词。 @Servy 完全正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    相关资源
    最近更新 更多