我试图通过解析XML模板来执行在运行时动态创建的方法。我从" DebugView"得到了以下内容:在编译之前的表达式lambda:
.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()
}
}
}
并且这样称呼它,确保myReportWriter
和myData
之前不是null
:
Action<IReportWriter, Object> Formatter = methodExpression.Compile();
Formatter(myReportWriter, myData)
在我的跟踪输出中,我甚至没有得到&#34;初始化驱动程序&#34;抛出空引用异常之前的输出。
仔细观察调试输出显示它实际上是进入&#34;初始化驱动程序&#34;并在第一个.Block内部的$ writer上为null添加另一个调试检查,显示(writer == null) == true
。现在,问题是:为什么$ writer在传入方法调用时为null?
答案 0 :(得分: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()
}
}
}