2016-06-19 2 views
0

MemberExpression이 객체 인스턴스에 속하는지 또는 표현식의 매개 변수인지 여부를 확인하려고합니다. 실행 가능한 솔루션이라고 생각하는 것을 생각해 냈습니다.하지만 SE에서 먼저 실행하고 싶습니다. 우선이 두 식을 가지고 :MemberExpression이 인스턴스에 속하는지 여부 확인

var myClassInstance = new MyClass(); 

Expression<Func<MyClass, bool>> exp1 = mc => myClassInstance.MyBool; 
Expression<Func<MyClass, bool>> exp2 = mc => mc.MyBool; 

exp1는 지역 변수/필드에 대한 참조를 포함합니다.

Expression.Lambda<Func<object>>(Expression.Convert(exp1.Body as MemberExpression, typeof(object))).Compile(); 

exp2에서 .MyBool 개체 참조에서 아니지만, paremeter : 더 아래로 내 코드에서, .MyBool는 다음과 같이 그 값을 검색하기 위해 컴파일됩니다. .MyBool 표현식을 컴파일하려고하면 variable 'mc' of type 'ConsoleLol.MyClass' referenced from scope '', but it is not defined 예외가 발생합니다.

약간의 수고 후,이 잠재적 인 해결책을 마련했습니다

var exp1parent = (exp1.Body as MemberExpression).Expression; 
var exp2parent = (exp2.Body as MemberExpression).Expression; 

Console.WriteLine(exp1parent.NodeType); 
Console.WriteLine(exp2parent.NodeType); 

표현의 부모 표현이 인스턴스가 아닌 경우에는 NodeType 속성이 Parameter 될 것입니다 것으로 보인다. 그렇지 않은 경우, 다른 경우 (이 경우 MemberAccess)가됩니다.

이 결론에서 정확합니까? 아니면이 검사를 수행하는보다 이상적인 방법이 있습니까?

+0

실제로 무엇을하려고하는지 설명해 주시겠습니까? 'Expression >'이라는 표현식은'MyClass'를 전달하지 않는 것처럼 보이는 이유는 무엇입니까? 이 모든 것을 피할 수있는'Expression '을 사용하지 않으시겠습니까? – svick

+0

@svick 무슨 뜻인지 확실하지 않습니다. 'Func '은 매개 변수로'MyClass'를 받아 들여'bool'을 반환하도록 정의됩니다. 게다가,이 함수를 사용하여 표현식을 SQL로 변환하기 때문에 MyClass가 필요하다.표현식이 인스턴스 멤버에 속하는지 여부를 알아야만 값을 얻기 위해 컴파일할지 또는 사용자 정의 SQL 함수로 표현식을 변환할지 결정할 수 있습니다. 제한된 공간으로 모든 것을 자세하게 설명하기가 어렵습니다. – oscilatingcretin

답변

0

정확하게 이해한다면 SQL 공급자를 만들고 있으므로 SQL로 변환 할 수없는 모든 내용을 평가해야합니다. 이를 수행하는 방법에 대한 설명은 Matt Warren의 기사 Building an IQueryable Provider – Part III에 있거나 iqtoolkit 라이브러리의 PartialEvaluator으로 사용할 수 있습니다.

+0

저는 표현식 트리를 되풀이하는 메소드를 작성하여이 모든 작업을 이미 거의 완료했습니다. 내가 OP에서 언급 한 바와 같이, 내가하고 싶은 것을 설명하기는 어렵지만 멤버 나 메소드를 컴파일할지 또는 멤버를 커스텀 SQL 표현식으로 변환 할지를 알아야한다 (예 :'mc .FirstName.Length == 10 'to'length (FirstName) = 10') 내 SQL에서) – oscilatingcretin

0

Op는 내 자신의 질문에 대한 대답으로 여기에 있습니다.

이 작업이 진행 중일 수 있지만 지금까지 작동합니다. 표현식 트리를 걷고 속성식이 데이터베이스 필드로 해석되어야하는지 아니면 SQL 값 매개 변수에 대해 컴파일되어야하는지 결정하려고 할 때식이 람다 식 매개 변수에서 오는 것인지 알아야합니다. 그렇지 않으면 컴파일/호출하려고하면 내 OP에서 언급 한 오류가 발생합니다.

다음은 내가 처음에 가지고있는 것들입니다. 기본적으로 부모 표현식 NodeType == ExpressionType.Parameter 또는 부모 표현식이 null이 될 때까지 표현식 트리를 계속 움직입니다. 전자는 자손 매개 변수이므로 컴파일하지 마십시오. 후자는 데이터베이스 필드를 나타내므로 적절하게 구문 분석합니다.

public static bool IsParameterDescendent(this Expression Expression) 
{ 
    var pe = Expression; 

    while (pe != null && pe.NodeType != ExpressionType.Constant) 
    { 
     if (pe.NodeType == ExpressionType.MemberAccess) 
     { 
      pe = pe.TryCast<MemberExpression>().Expression; 
     } 
     else if (pe.NodeType == ExpressionType.Call) 
     { 
      pe = pe.TryCast<MethodCallExpression>().Object; 
     } 

     if (pe?.NodeType == ExpressionType.Parameter) return true; 
    } 

    return false; 
} 

편집 : 당신이 모두이 작업을 수행하는 것을 피할 수 한 가지 방법은 항상 연산자와 오른쪽의 호출 가능한/값 공급자의 왼쪽에있는 데이터베이스 속성을 넣어 자신을 훈육된다. 나는이 방법으로 제한되는 것을 좋아하지 않는다.