2016-09-18 2 views
1

분명히 드러납니다. 나는 표현식으로 런타임 마술을한다. 내 단위 테스트는 예외를 던졌습니다. 왜냐하면, 제가하고있는 일은 상당히 복잡하고 실패하는 것이 명백하기 때문입니다.런타임에 액세스 예외가 발생했습니다.

생성 된 대리자를 어떻게 디버깅 할 수 있는지 모르겠으므로 해결 방법으로 Console에 예외를 기록하는 try-catch를 삽입하고 싶습니다.

예외 변수에 액세스하는 방법을 알 수 없습니다. 변수는 CatchBlock -class에 의해 노출됩니다. 하지만 범위를 벗어난 팩토리 메서드에서는 본문을 통과해야합니다.

어떻게 액세스 할 수 있습니까? 나는 이것을 할 수있는 합법적이고 해킹되지 않는 방법을 보지 못하며 매우 특별한 주제이기 때문에 인터넷에서 찾을 수있는 문서/정보는 거의 없다. 나는 필사적으로 같은 문제를 해결하기 위해 노력했다

// The actual code 
BlockExpression block = Expression.Block(new[] {messageParam, objectParam}, 
    callExpressions.ToArray()); 

// The catch block around it 
CatchBlock catchExpression = Expression.Catch(typeof(Exception), 
    Expression.Call(typeof(Console).GetMethod(nameof(Console.WriteLine), 
      BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new[] {typeof(string)}, 
      null), 
     Expression.Call(// Here should be the ParameterExpression 
      typeof(Exception).GetProperty(nameof(Exception.Message), 
       BindingFlags.Public | BindingFlags.Instance).GetMethod))); 
// The try-block for the catch 
TryExpression tryExpression = Expression.TryCatch(block, catchExpression); 

// Compilation ... 
+0

디버거를 사용할 때 생성되는 "코드"표현식을 볼 수 있습니다. 따라서 어디를 잘못 보는지 알 수 있습니다. 컴파일 한 후에는 생성 된 코드를 볼 수 없으므로 개발할 때 최종 Expression.Lamba를 임시 변수에 붙이면 모든 코드가 제거됩니다. 그렇게하면 최종 코드를 볼 수 있습니다. 또한 코드가 생성 된 것을 볼 때 모든 것이 어떻게 함께 연결되는지 더 잘 이해할 수 있습니다. 문제가있는 경우 생성 된 코드를 게시하십시오. – SledgeHammer

+0

아, 그래도 컴파일하기 전에 LambdaExpression을 살펴볼 때 코드를 볼 수 있습니까? 알아 둘만한. 음, 구식 브레인 스토밍 방법을 사용하여 문제를 발견했습니다. 변수를 블록에 전달하여 NullReferenceException을 유발하는 변수를 재정의했습니다. - 문제는 실행 중에 분명히 발생했습니다. 코드 생성 자체가 유효하기 때문에 실패하지 않습니다. – SharpShade

답변

1

:

여기에 지금까지 내 코드입니다. 나는 매우 유사한 이유 - 역동적 인 표현에 대한 목적을 추적합니다. 해결책은 different overload of Expression.Catch을 사용하는 것만큼 쉽습니다.

매우 드문 문서 및 예제로 인해 알아 내기가 어려웠습니다.

그래서 경우에 다른 사람은 비슷한 기능을 필요 - 여기에 아주 기본적인 작업 예를 간다 (당신이 당신의 로거 등을 로그인 사용자 정의 식 캐치 본체 교체 할 수 있습니다) :

var parExcep = Expression.Parameter(typeof (Exception), "exc"); 

MethodInfo excMsg = typeof(Exception).GetProperty("Message", 
    BindingFlags.Public | BindingFlags.Instance).GetMethod; 


TryExpression tryCatchExpr = 
    Expression.TryCatch(
     Expression.Block(
      Expression.Throw(Expression.Constant(new DivideByZeroException())), 
      Expression.Constant("Try block") 
      ), 
     Expression.Catch(
      parExcep, 
      Expression.Call(parExcep, excMsg) 
      ) 
     ); 

Console.WriteLine(Expression.Lambda<Func<string>>(tryCatchExpr).Compile()()); 

인쇄 아웃 :

0으로 나누려고했습니다.

관련 문제