Come posso eseguire il debug o impostare un'istruzione break all'interno di un albero di espressioni compilato?

c# debugging expression-trees linq

Domanda

Quando una libreria esterna contiene un provider LINQ e genera un'eccezione durante l'esecuzione di un albero di espressioni dinamiche, come posso interrompere quando viene lanciata quell'espressione?

Ad esempio, utilizzo un provider LINQ2CRM di terze parti, che mi consente di chiamare il metodo Max<TSource, TResult>() di IQueryable , ma quando lancia un InvalidCastException , non riesco a interromperlo quando viene Max<TSource, TResult>() l'eccezione, rendendo è difficile rivedere lo stack-trace perché è già aperto quando il debugger lo interrompe nel mio codice. Ho impostato "break on throw" per l'eccezione citata. Le mie impostazioni di debug sono:

inserisci la descrizione dell'immagine qui


Chiarimento su dove esattamente vorrei rompere. Non voglio interrompere l'espressione LINQ, ma, al contrario, voglio interrompere quando viene eseguito l'albero dell'espressione, o, in altre parole, quando il metodo di estensione IQueryable Max() chiama l'override fornito dal provider LINQ. La parte superiore dello stacktrace appare così, che è il punto in cui vorrei entrare (o fare un passo, o qualsiasi altra cosa):

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

Risposta accettata

Potrei non capire il problema, ma invece di rompere la linea (che non sembra possibile), sarebbe sufficiente mettere un try-catch all'interno del proprio albero delle espressioni e registrare l'eccezione?

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

Uscita della console:

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 )


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché