W poprzednim poście opisałem czym są Programmable Data Query i jak zdefiniować wykorzystujące je zdarzenie IntelliTrace. Teraz pora na przedstawienie przykładowej implementacji PDQ. Zacznijmy jednak od przypomnienia do czego służą poszczególne metody interfejsu IProgrammbleDataQuery. Potrzebne informacje zamieściłem na poniższej mapie myśli:
Poniższe PDQ może zostać użyte z każdym zdarzeniem diagnostycznym. Jest proste ale nie znajdziemy analogicznego w bibliotece Microsoft.VisualStudio.DefaultDataQueries.dll. Bardzo dobrze nadaje się jako baza to tworzenia bardziej skomplikowanych rozwiązań.
Jego działanie polega na odczytaniu wartości parametrów aktualnych wywołania metody lub wartości zwróconej przez metodę i stworzeniu na tej postawie opisu zdarzenia. Dla przypomnienia opis zdarzenia wyświetlany jest przez Visual Studio w czasie przeglądania nagranego logu IntelliTrace.
Poniższe PDQ może zostać użyte z każdym zdarzeniem diagnostycznym. Jest proste ale nie znajdziemy analogicznego w bibliotece Microsoft.VisualStudio.DefaultDataQueries.dll. Bardzo dobrze nadaje się jako baza to tworzenia bardziej skomplikowanych rozwiązań.
Jego działanie polega na odczytaniu wartości parametrów aktualnych wywołania metody lub wartości zwróconej przez metodę i stworzeniu na tej postawie opisu zdarzenia. Dla przypomnienia opis zdarzenia wyświetlany jest przez Visual Studio w czasie przeglądania nagranego logu IntelliTrace.
public class Test : IProgrammableDataQuery { public object[] EntryQuery(object thisArg, object[] args) { return args; } public object[] ExitQuery(object returnValue) { return new object[] { returnValue }; } public List<CollectedValueTuple> FormatCollectedValues(object[] results) { List<CollectedValueTuple> list = new List<CollectedValueTuple>(); for (int i = 0; i < results.Length; ++i) { list.Add(new CollectedValueTuple( String.Format("Result{0}", i), String.Format("'{0}'",results[i]), "string")); } return list; } public string FormatLongDescription(object[] results) { try { StringBuilder builder = new StringBuilder(); builder.AppendFormat("Collected objects ({0}): ", results.Length); bool flag = true; foreach (var r in results) { if (!flag) { builder.Append(", "); } flag = false; builder.AppendFormat("'{0}'", r); } return builder.ToString(); } catch (Exception ex) { return ex.ToString(); } } public string FormatShortDescription(object[] results) { return FormatLongDescription(results); } public List<Location> GetAlternateLocations(object[] results) { return null; } }Implementacja EntryQuery oraz ExitQuery jest trywialna. W żaden sposób nie modyfikuję danych wejściowych i po prostu przekazuje je dalej. FormatLongDescription wykorzystuje te dane do stworzenia opisu zdarzenia po prostu sklejając poszczególne elementy tablicy. Dla zdarzenia przeznaczonego do analizowania danych wejściowych będą to parametry aktualne, a dla zdarzenia przeznaczonego do analizowania danych wyjściowy wynik zwrócony przez metodę. FormatShortDescription po prostu wywołuje FormatLongDescription. Logika FormatCollectedValues też nie jest skomplikowana. Metoda ta po prostu zwraca dane jakie otrzymała na wejściu, dodatkowo nadając im etykiety Result0, Result1 itd.