¿Cómo puedo depurar o establecer una instrucción break dentro de un árbol de expresiones compiladas?

c# debugging expression-trees linq

Pregunta

Cuando una biblioteca externa contiene un proveedor LINQ y produce una excepción al ejecutar un árbol de expresiones dinámicas, ¿cómo puedo romper cuando se lanza esa expresión?

Por ejemplo, uso un proveedor LINQ2CRM de terceros, que me permite llamar al Max<TSource, TResult>() de IQueryable , pero cuando lanza una excepción InvalidCastException , no puedo interrumpir en el acto cuando se produce la excepción. es difícil revisar el seguimiento de la pila porque ya está desconectado cuando el depurador lo rompe en mi código. He establecido "break on throw" para la excepción mencionada. Mis ajustes de depuración son:

introduzca la descripción de la imagen aquí


Aclaración sobre dónde exactamente querría romper. No quiero romper en el lado de la expresión LINQ, pero en su lugar, yo quiero romper cuando se ejecuta el árbol de expresión, o, dicho en otras palabras, cuando el IQueryable método de extensión Max() llama a la anulación proporcionada por el proveedor de LINQ. La parte superior del stacktrace se ve así, que es donde me gustaría entrar (o pasar, o lo que sea):

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

Respuesta aceptada

Puede que no esté entendiendo el problema, pero en lugar de romper la línea (lo que no parece ser posible), ¿sería suficiente poner un try-catch dentro de su árbol de expresiones y registrar la excepción?

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

Salida de consola:

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 )


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow