2012-06-13 12 views
10

Cuando una biblioteca externa contiene un proveedor de LINQ y arroja una excepción al ejecutar un árbol de expresiones dinámicas, ¿cómo puedo romper cuando se lanza esa expresión?¿Cómo puedo depurar o establecer una declaración de interrupción dentro de un árbol de expresiones compilado?

Por ejemplo, utilizo un tercero proveedor de LINQ2CRM partido, lo que me permite llamar al método de IQueryableMax<TSource, TResult>(), pero cuando se lanza una InvalidCastException, no llego a romper en el lugar cuando se produce la excepción, por lo que es difícil de revise el stack-trace porque ya está desdoblado cuando el depurador lo rompe en mi código. He establecido "break-in-throw" para la excepción mencionada. Mi configuración de depuración son:

enter image description here


Aclaración sobre el lugar exacto que me gustaría romper. I no desea romper el lado de la expresión LINQ, pero en su lugar, quiero romper cuando se ejecuta el árbol de expresiones, o, dicho de otro modo, cuando el método de extensión IQueryableMax() llama a la anulación proporcionada por el proveedor LINQ. La parte superior de la StackTrace se parece a esto, que es donde me gustaría romper el interior (o paso a paso, o lo que sea):

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

¿Quiere decir pegar un punto de interrupción en parte de una expresión lambda en uno de esos métodos? –

+0

No estoy seguro si [esto ayuda] (http://www.simple-talk.com/dotnet/.net-framework/linq-secrets-revealed-chaining-and-debugging/), pero estoy haciendo una búsqueda ahora ya que esto es interesante Todos los caminos parecen ir a LinqPad. Sin embargo, no puedo ver cómo se podría romper sin el código fuente, y luego cuando se tiene la fuente, ¿no se puede simplemente romper el punto en el proveedor responsable de 'Max'? –

+0

La sección [Árboles de expresiones] (http://msdn.microsoft.com/en-us/library/bb397951.aspx) MSDN también tiene una sección para [Depurar árboles de expresiones] (http://msdn.microsoft.com/ en-us/library/ee725345). Creo que aquí es donde tengo que dejar de buscar y volver al trabajo ;-) –

Respuesta

4

yo no sea la comprensión del problema, pero en lugar de realmente rompiendo en la línea de (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 la 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) 
Cuestiones relacionadas