Использование дерева выражений для навигации и возврата объекта, которому принадлежит свойство - PullRequest
1 голос
/ 16 июля 2010

Учитывая выражение, которое указывает на свойство в графе объектов, я хочу получить экземпляр, которому принадлежит свойство, в этом графе.Я боролся.Текущий код просто дает мне System.InvalidOperationException: лямбда-параметр не находится в области действия

    [Test]
    public void TestExpression()
    {
        var person = new Person {Address = {Street = "Bank Street"}, Name = "Joe"};

        Expression<Func<Person, object>> exp = p => p.Address.Street;
        Assert.AreEqual("Bank Street", exp.Compile().Invoke(person));

        var owner = GetPropertyOwner(person, exp);
        Assert.AreEqual(owner, person.Address);
    }

    private object GetPropertyOwner<T>(T root, Expression<Func<T, object>> exp)
    {
        if (exp.Body is MemberExpression)
        {
            var member = exp.Body as MemberExpression;
            if (member.Expression is MemberExpression)
            {
                var parentMember = member.Expression as MemberExpression;
                //parent member will be {p.Address}
                //Now I'm trying to reconstruct an expression that I can combile
                var parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(T), "p");
                var lambdaExpression = System.Linq.Expressions.Expression.Lambda(parentMember, parameterExpression);
                //Next Linethrows  System.InvalidOperationException : Lambda Parameter not in scope
                var found = lambdaExpression.Compile().DynamicInvoke(person);
                return found;
            }
        }

        return new object();
    }

1 Ответ

2 голосов
/ 16 июля 2010

Объекты ParameterExpression сравниваются по равенству ссылок, а не по имени, поэтому параметр "p", который принимает lambdaExpression, отличается от параметра, используемого в parentMember.Вам нужно будет использовать тот же экземпляр ParameterExpression при создании новой лямбды.Попробуйте:

var parameterExpression = exp.Parameters[0];
...