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()
        }
    }
}

そして、それを次のように呼び出して、 and が事前ではないことを確認myReportWriterします。myDatanull

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

私のトレース出力では、null 参照例外がスローされる前に「ドライバーの初期化」出力さえ取得していません。

デバッグ出力をよく見ると、実際には「ドライバーの初期化」に到達し、最初の .Block のすぐ内側にある $writer に null の別のデバッグ チェックを追加すると、.Block が表示され(writer == null) == trueます。さて、問題は、メソッド呼び出しに渡されたときに $writer が null になるのはなぜですか?

4

1 に答える 1

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()
        }
    }
}
于 2013-08-20T16:07:39.230 に答える