2016-09-18 61 views
1

明显的情况。我用表达式做了一些运行时魔术。我的单元测试会引发异常,因为我正在做的事情非常复杂,因此显然会失败。运行时生成表达式的访问异常

我不知道我怎么可能调试生成的代表,从而解决办法,我想插入一个try-catch它记录异常到控制台。

我只是不明白我如何访问异常变量。该变量由CatchBlock-类暴露。但是我必须在工厂方法中通过它的身体,这是超出范围的。

我该如何访问它?我没有看到任何合法的,不冒险的方式来做到这一点,因为这是一个非常不寻常的话题,在互联网上几乎没有任何文档/信息可以找到。

这里是到目前为止我的代码:

// 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()()); 

打印出:

试图除以零。