2012-06-13 4 views
10

Gdy biblioteka zewnętrzna zawiera dostawcę LINQ i zgłasza wyjątek podczas wykonywania drzewa wyrażeń dynamicznych, w jaki sposób mogę przerwać wykonywanie wyrażenia?Jak mogę debugować lub ustawić instrukcję break w skompilowanym drzewie wyrażeń?

Na przykład, używam trzeciego dostawcę partia LINQ2CRM, która pozwala mi nazwać metodę IQueryableMax<TSource, TResult>(), ale kiedy rzuca InvalidCastException, nie udało mi się przełamać na miejscu, gdy jest wyjątek, utrudniając przejrzyj śledzenie stosu, ponieważ jest już rozwijane, gdy debugger zepsuje go w moim kodzie. Ustawiłem "break on throw" dla wspomnianego wyjątku. Moje ustawienia debugowania są:

enter image description here


Wyjaśnienie gdzie dokładnie chciałbym złamać. I Do not chcę, aby złamać w boku Wyrażenie LINQ, ale zamiast tego chcę złamać, gdy drzewo wyrażenie jest wykonywane, lub, innymi słowy, kiedy IQueryable metoda rozszerzenia wywołuje zastąpienie dostarczone przez dostawcę LINQ. Wierzchołek stacktrace wygląda to, co jest gdzie chciałbym złamać wewnątrz (lub krok po kroku, lub cokolwiek):

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

Czy to znaczy trzymać przerwania w ramach wyrażenia lambda w jednej z tych metod? –

+0

Nie jestem pewien, czy [to pomaga] (http://www.simple-talk.com/dotnet/.net-framework/linq-secrets-revealed-chaining-and-debugging/), ale teraz szukam ponieważ jest to interesujące. Wszystkie drogi wydają się iść do LinqPada. Nie widzę sposobu, w jaki mógłbyś go złamać bez kodu źródłowego, a kiedy masz źródło, czy nie możesz po prostu złamać punktu w części dostawcy odpowiedzialnego za 'Max'? –

+0

Sekcja MSDN (Wyrażenie drzewa) (http://msdn.microsoft.com/en-us/library/bb397951.aspx) zawiera sekcję [Debugowanie wyrażeń drzewa] (http://msdn.microsoft.com/ en-us/library/ee725345). Myślę, że właśnie tu muszę przestać szukać i wracać do pracy ;-) –

Odpowiedz

4

I nie może być zrozumienie problemu, ale zamiast faktycznie zerwania na linii (co nie wydaje się możliwe), czy wystarczy umieścić próbkę w drzewie wyrażeń i zarejestrować wyjątek?

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

wyjście konsoli:

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)