You have many options, I'll show them from most powerful to most simple one.
Custom Visualizer
You may take a look to Debugger Visualizers. You can provide your own UI for debugging your classes. Idea itself is pretty similar to how PropertyGrid
editors works (IVisualObjectProvider
and DialogDebuggerVisualizer
) and you may even reuse that code to inspect your object with a property grid. Let's see a very trivial - and untested - example (adapted from MSDN).
public class PropertyGridInspectorVisualizer : DialogDebuggerVisualizer
{
protected override void Show(
IDialogVisualizerService windowService,
IVisualizerObjectProvider objectProvider)
{
var propertyGrid = new PropertyGrid();
propertyGrid. Dock = DockStyle.Fill;
propertyGrid.SelectedObject = objectProvider.GetObject();
Form form = new Form { Text = propertyGrid.SelectedObject.ToString() };
form.Controls.Add(propertyGrid);
form.ShowDialog();
}
// Other stuff, see MSDN
}
To use this custom visualizer you just need to decorate your class as follow:
[DebuggerVisualizer(typeof(PropertyGridInspectorVisualizer))]
class Dimension
{
}
Proxy Object
There is another way to have an alternative debug view of an object: DebuggerTypeProxyAttribute
. You won't see object you're debugging but a custom proxy (that can be shared across all your classes and rely on TypeConverter
). In short it's something like this:
[DebuggerTypeProxy(CustomDebugView)]
class Dimension
{
}
// Debugger will show this object (calling its ToString() method
// as required and showing its properties and fields)
public class CustomDebugView
{
public CustomDebugView(object obj)
{
_obj = obj;
}
public override string ToString()
{
// Proxy is much more powerful than this because it
// can expose a completely different view of your object but
// you can even simply use it to invoke TypeConverter conversions.
return _obj.ToString(); // Replace with true code
}
private object _obj;
}
Non-Invasive ToString() Replacement
Last way to do it (AFAIK) is to use DebuggerDisplayAttribute
(MSDN for details). You can handle very complex cases but it's pretty handy in many situations: you build a string that will be visualized by debugger when you inspect that object. For example:
[DebuggerDisplay("Architectural dimension = {Architectural}")]
class Dimension
{
}