2011-02-25 10 views
1

하나의 객체를 매개 변수로 사용하여 궁극적으로 객체를 반환하는 LambdaExpression이 있습니다. 테스트 목적으로, 여기에 람다 (내가 실제로 전달하는 것과 일치하는 생성 된 길이)가 있습니다.이 람다는 DateTime 박스를 객체로 반환합니다. 이 작업을 위해 LambdaExpression은 XmlNode를 사용하여 개체를 반환합니다. 개체를 반환해야합니다. 실제 반환 형식은 DateTime, bool, int, decimal, XmlDocument 중 하나 일 수 있습니다. 일반적인 생각은 파서의 어느 곳에서나이 람다가 만들어지고 값을 추출한다는 것입니다 그것의 입력 매개 변수에서 입력 한 그것을 반환하지만, 개체에 boxed.Expression.LessThan 대 LambdaExpression <Func <ParamType, object >>

 XmlNode node = null; 
     ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance"); 
     ParameterExpression result = Expression.Parameter(typeof(object), "result"); 
     LabelTarget blockReturnLabel = Expression.Label(typeof(object)); 
     BlockExpression block = Expression.Block(
          typeof(object), 
          new[] { result }, 
          Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))), 
          Expression.Return(blockReturnLabel, result), 
          Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object)))); 
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression); 

나중에 코드에서 , 우리가 <, < =,>,> =, ==를 평가하고 있으며! = 그래서 우리는

보통 다른 표현이 LambdaExpression의 결과를 비교하려면, 우리는 LambdaExpression이 Expression.LessThan의 왼쪽에 있다고 가정 할 수 있습니다. 오른쪽에있는 은 거의 모든 표현식이 될 수 있지만 입력 된 것으로 가정 할 수 있습니다. 즉, ConstantExpression 또는 유사 할 수 있지만 ... 형식을 가질 수 있습니다.

이렇게하면 Expression.Invoke가 호출 될 때 LambdaExpression이 개체를 반환하고 RHS가 해당 형식이 되었기 때문에 Expression.LessThan [예를 들어]가 실패합니다.

LambdaExpression에서 반환 된 개체 내부의 상자 형식이 실제로 오른쪽에있는 형식과 비교된다고 가정합니다. 예 :

(object)5 < 6 

충돌없이 박스형을 박스 화되지 않은 유형과 비교할 수있는 표현식은 어떻게 작성합니까? linqpad에서 여러 가지 순열을 시도했습니다. 보통 C#에서 이것을 작성하는 것을 포함하여 - 즉 표현식이 없으면 중첩 된 if-then-else가 있지만 제대로 작동하지는 않습니다. 일반적으로, 난 아마 이런 걸 쓸 것 : O를 가정이와

/* 
int i = 3; 
object o = (object)i; 
int compare = 4; 
*/ 
DateTime dt = DateTime.Now; 
object o = (object)dt; 
DateTime compare = DateTime.Now.AddSeconds(1); 

bool b = false; 
if(o.GetType().IsAssignableFrom(compare.GetType())) 
{ 
    if(o is int) 
    { 
     b = (int)o < (int)(object)compare; 
    } 
    if(o is DateTime) 
    { 
     b = (DateTime)o < (DateTime)(object)compare; 
    } 
    if(o is decimal) 
    { 
     b = (decimal)o < (decimal)(object)compare; 
    } 
} 
Console.WriteLine(b); 

을 실제로 그들 중 하나가 개체로 박스 동일한 유형 및있는 비교 우리는 여전히 < 작업을 수행 할 수 있습니다 ..

그래서 내 질문은 왼쪽에 LambdaExpression이 있고 위의 코드는 어떻게 작성합니까? [두식이 같은 형식이 아닌 경우 잘못된 결과가 더 좋음을 나타냅니다. 충돌]

누군가가 도울 수 있기를 바랍니다.

,

가레스

답변

1

내가 충돌없이 언 박싱 유형으로 박스 타입을 비교할 수있는 식을 작성하려면 어떻게합니까?

다음과 같이 Expression.Unbox 메서드를 사용할 수 있습니다. "명시 적 unboxing을 나타내는 UnaryExpression을 만듭니다."

은의이 (int)(object)5 < 6 예를 보자 :

그래서 내 질문에 내가 왼쪽에 LambdaExpression이있을 때 위의 코드를 작성하고,에 표현 어떻게, 추측
// boxed int 
var left = Expression.Constant(5, typeof(object)); 

// int 
var right = Expression.Constant(6, typeof(int)); 

// More generally, you can use right.Type instead of typeof(int) 
// if its static type is appropriate. 
// Otherwise, you may need to unbox it too. 
var unboxedLeft = Expression.Unbox(left, typeof(int)); 

var lessThanEx = Expression.LessThan(unboxedLeft, right);  
var expression = Expression.Lambda<Func<bool>>(lessThanEx, null); 

// True : (int)(object)5 < 6 
bool b = expression.Compile()(); 

[두 개가 같은 유형이 아닌 경우 오류가 발생하면 오류가 발생합니다]

이 경우, 다음과 같은 조건을 검사하는 조건식을 작성할 수 있습니다. boxed 객체의 런타임 유형은 오른쪽면의 유형과 동일하며 unboxing + less-than 비교가있는 경우 비교를 수행하거나 그렇지 않으면 false를 반환합니다.

예.

// From earlier 
var left = ... 
var right = ... 
var lessThanEx = ... 

var body = Expression.Condition(Expression.TypeEqual(left, right.Type), 
           lessThanEx, 
           Expression.Constant(false)); 

var expression = Expression.Lambda<Func<bool>>(body, null); 
+0

에서 작동하는 것 같다. –

+0

좋습니다. Expression.Condition은 Expression.IfThenElse와 유사합니다. 제가 말할 수있는 한, 그것은 Ternary bool과 더 유사합니까? true : false –

+0

그는 아마도 비교할 결과가 아닌 표현을 비교하기를 원합니다. 오해했습니다. –

1

당신의 사람들과 함께 내 원래의 게시물을 결합 answers-이 영업 이익은 논리를 비교 이내에 식을 선호 아마 생각 Em..I LinqPad

XmlNode node = null; 
ParameterExpression instanceExpression = Expression.Parameter(typeof(XmlNode), "instance"); 
ParameterExpression result = Expression.Parameter(typeof(object), "result"); 
LabelTarget blockReturnLabel = Expression.Label(typeof(object)); 
BlockExpression block = Expression.Block(
        typeof(object), 
        new[] { result }, 
        //this would normally be a function invoke 
        Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))), 
        Expression.Return(blockReturnLabel, result), 
        Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object)))); 
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression); 

var left = Expression.Invoke(lax, instanceExpression); 
//false result 
//var right = Expression.Constant(5, typeof(int)); 
//true result 
var right = Expression.Constant(DateTime.Now, typeof(DateTime)); 

var unboxedLeft = Expression.Unbox(left, right.Type); 
var lessThanEx = Expression.LessThan(unboxedLeft, right);  

var body = Expression.Condition(Expression.TypeEqual(left, right.Type), lessThanEx, Expression.Constant(false)); 
var expression = Expression.Lambda<Func<XmlNode, bool>>(body, instanceExpression); 

bool b = expression.Compile()(node); 
Console.WriteLine(b); 
+0

Expression Trees를 통해 실수를 범할 수는 있지만 StackOverflow에서 코드 블록을 파악할 수는 없습니다. –

+0

그냥 들여 쓰기 4를 사용하십시오. 또는 들여 쓰기 0을 사용하여 코드를 선택한 다음 코드 샘플 단추를 누르십시오. – Ani