Roslyn scripting: Line number information for run time exceptions

孤者浪人 提交于 2019-12-03 21:14:46

I got something working by emitting an (in-memory) assembly with debug information.

Example code:

var code = @"
var a = 0;
var b = 1 / a;
";

var script = CSharpScript.Create(code);
var compilation = script.GetCompilation();
var ilstream = new MemoryStream();
var pdbstream = new MemoryStream();
compilation.Emit(ilstream, pdbstream);

var assembly = Assembly.Load(ilstream.GetBuffer(), pdbstream.GetBuffer());
var type = assembly.GetType("Submission#0");
var factory = type.GetMethod("<Factory>");
var submissionArray = new object[2];
Task<object> task = (Task<object>)factory.Invoke(null, new object[] { submissionArray });

try
{
    await task;
}
catch (DivideByZeroException dbze)
{
    Console.WriteLine(dbze.StackTrace);
}

The output is (notice the :line 3 in the stack trace):

   at Submission#0.<<Initialize>>d__0.MoveNext() in :line 3
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at UnitTests.ExploreRoslyn.<ExploreEmittingAssembly>d__13.MoveNext() in D:\dev\misc\netmockery\UnitTests\ExploreRoslyn.cs:line 151

Now obviously this is a bit of a hack, and I'm not really happy with the hardcoded script engine implementation details (Submission#0, <Factory>), plus I don't really know what I'm doing. There should be (and maybe there is?) a better way.

Update

Created issue https://github.com/dotnet/roslyn/issues/13482 in the Roslyn issue tracker.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!