Ответ 1
Чтобы сделать отладку IL, вам необходимо скомпилировать код в отладочную сборку. Также существует немедленный недостаток в том, что сборка не будет собираться GC. Для этого выполните AppDomain.CurrentDomain.DefineDynamicAssembly
, затем вы вызываете DefineDynamicModule
и определяете модуль в сборке. Чтобы сделать его отлаживаемым, вам нужно установить некоторые атрибуты:
DebuggableAttribute.DebuggingModes attrs =
DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.DisableOptimizations;
Type[] argTypes = new Type[] { typeof(DebuggableAttribute.DebuggingModes) };
Object[] argValues = new Object[] { attrs };
_myAssembly.SetCustomAttribute(new CustomAttributeBuilder(
typeof(DebuggableAttribute).GetConstructor(argTypes), argValues)
);
_myModule.SetCustomAttribute(new CustomAttributeBuilder(
typeof(DebuggableAttribute).GetConstructor(argTypes), argValues)
);
Наконец, при испускании IL вы вызываете MarkSequencePoint
, чтобы отметить строки для следующих инструкций IL.
Создание отлаживаемых сайтов вызовов DLR кажется странным для меня - обычно ваш сайт вызова не будет содержать какой-либо код пользователя. Скорее, он будет содержать код для выполнения операции, и исходный код, связанный с этим кодом, отсутствует. Но позвольте сказать, что вы действительно хотите что-то сделать, чтобы связать с деревьями выражений, которые вы генерируете для сайта вызова. Для этого вам нужно сделать две вещи. Сначала хранится информация об отладке в дереве выражений - вы делаете это с помощью DebugInfoExpression
. Следующим является компиляция метода в метод отладки и предоставление этого делегата DLR.
Для компиляции метода вам необходимо использовать LambdaExpression<T>.CompileToMethod
. MethodBuilder
, который вам нужно предоставить, должен быть статическим методом, определенным в типе создаваемой ранее отлаживаемой сборки.
Для предоставления этому делегату DLR у вас есть два варианта. Вероятно, самым легким было бы фактически вернуть выражение, которое вызывает скомпилированный отлаживаемый делегат (просто удерживая его через константу). Более сложным, но в некотором смысле более элегантным способом было бы переопределить BindDelegate<T>
на сайте вызова и вернуть скомпилированный делегат. Это начинает вступать в создание соответствующего аргумента Expression
и вызывает методы Bind*
для создания дерева выражений, но вы сами.
Все это делается в внешнем слое DLR/IronPython/IronRuby - все доступно на ironpython.codeplex.com. Вы можете посмотреть CompilerHelpers.CompileToMethod
как пример выполнения компиляции, класса Snippets
(и связанных классов AssemblyGen
/TypeGen
/ILGen
) для создания отлаживаемых сборок и даже компилятора дерева выражений DLR ( в Runtime\Microsoft.Scripting.Core\Compiler
) для примера испускания информации о линии.