开发者

Parameter Not In Scope when Compiling LambdaExpression

开发者 https://www.devze.com 2023-02-13 18:06 出处:网络
I\'m doing a bit of work using reflection and want to create a LambdaExpression that I can run against a List<T> collection and intersect with a HashSet<int> collection to find any matches

I'm doing a bit of work using reflection and want to create a LambdaExpression that I can run against a List<T> collection and intersect with a HashSet<int> collection to find any matches.

My problem is that T does not imp开发者_StackOverflowlement a common base class or interface, hence the reflection on types and a requirement tp programatically build a Lambda expression.

I'f I knew my types, what I wnat to execute is:

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

I started mocking up a way to do this using LambdaExpression, but I can't get the thing to compile and can't seem to figure out how to do what it wants (i.e. feed in the variable for the HashSet<int>). My bodged attempt is below, does anyone have any suggestions as to how to get the LambdaExpression to compile, and how to actually execute it getting a List<myObject> out at the other end?

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

    }
}

Thanks in advance!


You need to include idList in the call to Expression.Lambda, and supply an argument in the final invoke (DynamicInvoke in your example). Or if it is meant to be fixed at {2,3,5}, replace idList with an Expression.Constant.

Note that if you want to get the performance, you need to use typed invoke, not DynamicInvoke.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号