2013-08-20 38 views
0

我想通过解析XML模板来执行在运行时动态创建的方法。我得到的来自表达拉姆达“的DebugView”以下是编译之前:执行表达式委托产生空引用异常

.Lambda #Lambda1<Reporting.Core.Formatter+WriterDriver>(
    Reporting.Core.IReportWriter $writer, 
    System.Object $data) { 
    .Block(
     Reporting.Core.IReportWriter $writer, 
     System.Object $data) { 
     .Call System.Diagnostics.Trace.WriteLine("Initialize Driver"); 
     .Call System.Diagnostics.Trace.WriteLine($writer); 
     .Block(Reporting.Core.IBannerWriter $bannerWriter) { 
      $bannerWriter = .Call $writer.WriteBanner(); 
      .Call System.Diagnostics.Trace.WriteLine($bannerWriter); 
      .Call $bannerWriter.WithLeftEntry(
       "Key1", 
       "Value1"); 
      .Call $bannerWriter.WithLeftEntry(
       "Key 2", 
       "Value 2"); 
      .Call $bannerWriter.WithRightEntry(
       "Another Key", 
       "Another Value"); 
      .Call $bannerWriter.EndBanner() 
     } 
    } 
} 

而且这样称呼它,确保myReportWritermyDatanull前:

Action<IReportWriter, Object> Formatter = methodExpression.Compile(); 
Formatter(myReportWriter, myData) 

在我的跟踪输出,我甚至没有得到“初始化驱动程序”输出引发空引用异常之前。

仔细看调试输出显示它实际上是“初始化驱动程序”,并且在第一个.Block内部的$ writer上添加了另一个调试检查,它显示(writer == null) == true。现在,问题是:为什么$ writer被传递给方法调用时为null?

回答

0

第一个.Block中的$ writer和$ data声明重写了.Lambda中的相同。

List<Expression> operations = new List<Expression>(); 
// populate operations... 

var methodBody = Expression.Block(new[] {writer, data}, operations); 
var lambda = Expression.Lambda<Action<IReportWrite, Object>>(methodBody, writer, data); 
while (lambda.CanReduce) lambda.Reduce(); 

return lambda.Compile() 

到:

从改变表达式生成逻辑

List<Expression> operations = new List<Expression>(); 
// populate operations... 

var methodBody = Expression.Block(operations); 
var lambda = Expression.Lambda<Action<IReportWrite, Object>>(methodBody, writer, data); 
while (lambda.CanReduce) lambda.Reduce(); 

return lambda.Compile() 

这产生一个工作表达式树如下:

.Lambda #Lambda1<Reporting.Core.Formatter+WriterDriver>(
    Reporting.Core.IReportWriter $writer, 
    System.Object $data) { 
    .Block() { 
     .Call System.Diagnostics.Trace.WriteLine("Initialize Driver"); 
     .Block(Reporting.Core.IBannerWriter $bannerWriter) { 
      $bannerWriter = .Call $writer.WriteBanner(); 
      .Call System.Diagnostics.Trace.WriteLine($bannerWriter); 
      .Call $bannerWriter.WithLeftEntry(
       "Key1", 
       "Value1"); 
      .Call $bannerWriter.WithLeftEntry(
       "Key 2", 
       "Value 2"); 
      .Call $bannerWriter.WithRightEntry(
       "Another Key", 
       "Another Value"); 
      .Call $bannerWriter.EndBanner() 
     } 
    } 
}