开发者

InvalidOperationException (Lambda parameter not in scope) when trying to Compile a Lambda Expression

开发者 https://www.devze.com 2022-12-28 15:05 出处:网络
I\'m writing an Expression Parser to make my API more refactor friendly and less error prone. basicaly, I want the user to write code like that:

I'm writing an Expression Parser to make my API more refactor friendly and less error prone. basicaly, I want the user to write code like that:

repository.Get(entity => entity.Id == 10);

instead of:

repository.Get<Entity>("Id", 10);

Extracting the member name from the left side of the binary expression was straight forward. The problems began when I tried to extract the value from the right side of the expression. The above snippet demonstrates the simplest possible case which involves a constant value but it can be much more complex involving closures and what not.

After playing with that for some time I gave up on trying to cover all the possible cases myself and decided to use the framework to do all the heavy lifting for me by compiling and executing the right side of the expression. the relevant part of the code looks like that:

public static KeyValuePair<string, object> Parse<T>(Expression<Func<T, bool>> expression)
{
    var binaryExpression = (BinaryExpression)expression.Body;

    string memberName = ParseMemberName(binaryExpression.Left);
    obje开发者_StackOverflow社区ct value = ParseValue(binaryExpression.Right);

    return new KeyValuePair<string, object>(memberName, value);
}

private static object ParseValue(Expression expression)
{
    Expression conversionExpression = Expression.Convert(expression, typeof(object));
    var lambdaExpression = Expression.Lambda<Func<object>>(conversionExpression);
    Func<object> accessor = lambdaExpression.Compile();
    return accessor();
}

Now, I get an InvalidOperationException (Lambda parameter not in scope) in the Compile line. when I googled for the solution I came up with similar questions that involved building an expression by hand and not supplying all the pieces, or trying to rely on parameters having the same name and not the same reference. I don't think that this is the case here because I'm reusing the given expression.

EDIT

This is one of the nonworking scenarios:

ExpressionParser.Parse(entity => entity.InternalClass.Id == entity.Id);

I would appreciate if someone will give me some pointers on this. Thank you.


The version with a constant works fine with the code as posted. Can you illustrate an example expression where it doesn't work?

When you see this, it means that your Right is trying to use a parameter; there is only one parameter in a Expression<Func<T, bool>> (the first one, of type T). For example, I would expect the following to break (and it does):

        // find people who are their own boss
        var pair = Parse<Foo>(entity => entity.Id == entity.ManagerId);

Re the complexity; there are a lot of cases that can be parsed without compile; I use a "try it and fallback to Compile" strategy. See the Evaluate and TryEvaluate methods, here.

0

精彩评论

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