문제

프로젝트에서 Lambda Expressions를 사용하여 타사 쿼리 API에 매핑하려고합니다. 그래서 나는 표현 트리를 손으로 구문 분석하고 있습니다.

내가 람다 표현을 전달하면 :

p => p.Title == "title"

모든 것이 작동합니다.

그러나 내 람다 표현이 다음과 같습니다.

p => p.Title == myaspdropdown.SelectedValue

.NET 디버거를 사용하여 해당 funciton의 실제 값이 표시되지 않습니다. 대신 나는 다음과 같은 것을 본다.

p => p.Title = (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)

무엇을 제공합니까? 그리고 표현의 오른쪽을 끈으로 잡으려고 할 때 (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue) 실제 값 대신. 실제 가치는 어떻게 얻습니까?

도움이 되었습니까?

해결책

람다 표현식을 발현 트리로 다룰 때 실행 가능한 코드가 없음을 기억하십시오. 오히려 당신은 당신이 쓴 표현을 구성하는 표현식 요소를 가지고 있습니다.

Charlie Calvert가 있습니다 좋은 게시물 그것은 이것에 대해 자세히 논의합니다. 디버깅 표현식을 위해 Expression Visualiser를 사용하는 예가 포함되어 있습니다.

귀하의 경우, 평등 표현의 8 번째 측면의 가치를 얻으려면 새로운 람다 표현식을 만들어 컴파일 한 다음 호출해야합니다.

나는 이것의 빠른 예를 함께 해킹했습니다 - 그것이 당신이 필요한 것을 전달하기를 바랍니다.

public class Class1
{
    public string Selection { get; set; }

    public void Sample()
    {
        Selection = "Example";
        Example<Book, bool>(p => p.Title == Selection);
    }

    public void Example<T,TResult>(Expression<Func<T,TResult>> exp)
    {
        BinaryExpression equality = (BinaryExpression)exp.Body;
        Debug.Assert(equality.NodeType == ExpressionType.Equal);

        // Note that you need to know the type of the rhs of the equality
        var accessorExpression = Expression.Lambda<Func<string>>(equality.Right);
        Func<string> accessor = accessorExpression.Compile();
        var value = accessor();
        Debug.Assert(value == Selection);
    }
}

public class Book
{
    public string Title { get; set; }
}

다른 팁

실제 값을 얻으려면 표현식 트리의 논리를 컨텍스트에 어떤 컨텍스트에 적용해야합니다.

표현 나무의 요점은 그들이 논리 표현식을 평가하기보다는 데이터로서. 람다 표현이 진정으로 의미하는 바를 해결해야합니다. 이는 로컬 데이터에 대해 일부를 평가하는 것을 의미 할 수 있습니다. 직접 결정해야합니다. 표현 나무는 매우 강력하지만 구문 분석하고 사용하는 것은 간단한 문제는 아닙니다. (LINQ 제공 업체를 작성한 사람에게 물어보세요 ... Frans Bouma는 여러 번 어려움을 겪었습니다.)

Bevan에게 똑같은 문제로 어려움을 겪고 있습니다. 확장에서 다음은 값을 추출하는 데 사용할 수있는 일반적인 패턴입니다 (쿼리 엔진에서 사용).

    [TestFixture]
public class TestClass
{
    [Test]
    public void TEst()
    {
        var user = new User {Id = 123};
        var idToSearch = user.Id;
        var query = Creator.CreateQuery<User>()
            .Where(x => x.Id == idToSearch);
    }
}

public class Query<T>
{
    public Query<T> Where(Expression<Func<T, object>> filter)
    {
        var rightValue = GenericHelper.GetVariableValue(((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right.Type, ((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right);
        Console.WriteLine(rightValue);
        return this;
    }
}

internal class GenericHelper
{
    internal static object GetVariableValue(Type variableType, Expression expression)
    {
        var targetMethodInfo = typeof(InvokeGeneric).GetMethod("GetVariableValue");
        var genericTargetCall = targetMethodInfo.MakeGenericMethod(variableType);
        return genericTargetCall.Invoke(new InvokeGeneric(), new[] { expression });
    }
}

internal class InvokeGeneric
{
    public T GetVariableValue<T>(Expression expression) where T : class
    {
        var accessorExpression = Expression.Lambda<Func<T>>(expression);
        var accessor = accessorExpression.Compile();
        return accessor();
    }
}

이해가 잘 모르겠습니다. 당신은 어디에서 "보고 있습니까? 디자인 시간 또는 런타임입니까? Lambda 표현은 본질적으로 익명의 대표로 생각 될 수 있으며, 이연된 실행과 함께 작동합니다. 따라서 실행 후 그 라인이 통과 될 때까지 할당 된 값을 볼 수 없어야합니다.
나는 그것이 당신이 실제로 당신이 의미하는 바라고 생각하지 않습니다 ... 당신이 질문을 조금 명확히한다면 아마도 내가 도울 수 있습니다 :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top