Как я могу отлаживать или устанавливать оператор break внутри скомпилированного дерева выражений?

Когда внешняя библиотека содержит поставщик LINQ и генерирует исключение при выполнении дерева динамических выражений, как я могу сломаться при вызове этого выражения?

Например, я использую сторонний поставщик LINQ2CRM, который позволяет мне вызвать метод Max<TSource, TResult>() IQueryable, но когда он выбрасывает InvalidCastException, я не могу сломаться на месте, когда возникает исключение, что затрудняет просмотр трассировки стека, поскольку он уже отключен, когда отладчик разбивает его в моем коде. Я установил "break on throw" для указанного исключения. Настройки моего отладки:

enter image description here


Разъяснение того, где именно я хотел бы сломаться. Я не хочу нарушать LINQ Expression, но вместо этого я хочу разбить, когда выполняется дерево выражений, или, другими словами, когда метод расширения IQueryable Max() вызывает переопределение, предоставляемое LINQ поставщик. Верхняя часть stacktrace выглядит так, вот где я хотел бы сломать внутри (или выполнить шаг или что-то еще):

at XrmLinq.QueryProviderBase.Execute[T](Expression expression)
at System.Linq.Queryable.Max[TSource,TResult](IQueryable`1 source, Expression`1 selector)

Ответ 1

Возможно, я не понимаю эту проблему, но вместо того, чтобы на самом деле ломаться на линии (что не представляется возможным), было бы достаточно поставить try-catch внутри вашего дерева выражений и записать исключение?

static void Main(string[] args)
{
    var logExceptionMethod = typeof (Program).GetMethod("LogException", BindingFlags.Static | BindingFlags.NonPublic);
    var createFileMethod = typeof (System.IO.File).GetMethod("Create", new[] {typeof(string)});

    // Parameter for the catch block
    var exception = Expression.Parameter(typeof(Exception));

    var expression =
        Expression.TryCatch(
        Expression.Block(typeof(void),
            // Try to create an invalid file
            Expression.Call(createFileMethod, Expression.Constant("abcd/\\"))),

            // Log the exception from the catch                  
            Expression.Catch(exception, Expression.Call(logExceptionMethod, exception)));

    Expression.Lambda<Action>(expression).Compile()();
}

static void LogException(Exception ex)
{
    Console.WriteLine(ex.Message + "\r\n" + ex.StackTrace);
}

Выход консоли:

The filename, directory name, or volume label syntax is incorrect.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.File.Create(String path)
at lambda_method(Closure )