编译LambdaExpression时参数不在范围内

时间:2011-02-25 23:29:38

标签: c# .net linq

我正在做一些使用反射的工作,并希望创建一个LambdaExpression,我可以针对List<T>集合运行并与HashSet<int>集合相交以查找任何匹配项。

我的问题是T没有实现公共基类或接口,因此对类型和需求的反思以编程方式构建Lambda表达式。

我知道我的类型,我要执行的是:

List<TestClass> entityList = GetOriginalList();
HashSet<int> idList = new HashSet<int>() { 1, 2, 3, 4 };
List<TestClass> filteredList = entityList.Where(o => idList.Contains(o.Id)).ToList();

我开始使用LambdaExpression嘲笑一种方法来做到这一点,但我无法得到编译的东西,似乎无法弄清楚如何做它想要的东西(即输入变量为HashSet<int>)。我的提出尝试在下面,有没有人有任何建议如何让LambdaExpression编译,以及如何实际执行它在另一端获得List<myObject>

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace PoCDynamicLambda
{
    class Program
    {
        class TestClass
        {
            private int _id;
            private string _value;

            public int Id { get { return this._id; } set { this._id = value; } }
            public string Value { get { return this._value; } set { this._value = value; } }

            public TestClass(int id, string value)
            {
                this._id = id;
                this._value = value;
            }
        }

        static void Main(string[] args)
        {
            List<TestClass> entityList = new List<TestClass>()
            {
                new TestClass(1, "One"),
                new TestClass(2, "Two"),
                new TestClass(3, "Three")
            };

            HashSet<int> idList = new HashSet<int>() { 2, 3, 5 };

            MethodInfo containsMethod = idList.GetType().GetMethod("Contains");
            ParameterExpression idListParam = Expression.Parameter(idList.GetType(), "idList");
            ParameterExpression objectListParam = Expression.Parameter(typeof(TestClass), "entityList");
            PropertyInfo idProperty = typeof(TestClass).GetProperty("Id");
            MemberExpression idMember = Expression.Property(objectListParam, idProperty);
            MethodCallExpression methodCall = Expression.Call(idListParam, containsMethod, idMember);
            LambdaExpression le = Expression.Lambda(methodCall, objectListParam);
            Console.WriteLine(le); // returns {entityList => idList.Contains(entityList.Id)}

            le.Compile(); // Error here
            Console.WriteLine(le.Compile().DynamicInvoke(entityList));

            Console.ReadLine();
        }

    }
}

提前致谢!

1 个答案:

答案 0 :(得分:1)

您需要在idList的调用中包含Expression.Lambda,并在最终调用中提供参数(在您的示例中为DynamicInvoke)。或者如果要将其修复为{2,3,5},请将idList替换为Expression.Constant

请注意,如果您想获得性能,则需要使用 typed 调用,而不是DynamicInvoke