[DebuggerTypeProxy] is very useful attribute when you have a class that inherits from another class and that one inherits from another one, and some of the classes contain collections of items and hundreds of properties that in fact are not important to you… Strictly speaking, when displaying class’ members while debugging makes you feel like quitting the job.
We decide how to display object while debugging
Exactly! You can set a proxy that will inform debugger how you want a type to be displayed!
Let’s write some simple example.
public class Vehicle { public int ProductionYear { get; set; } public string Model { get; set; } public decimal Price { get; set; } public List<string> Owners { get; set; } } public class Car : Vehicle { public List<string> Accessories { get; set; } public int DoorsCount { get; set; } }
In this example, I want to create an object of our type Car. As you can see, it inherites from Vehicle.
var car = new Car() { Model = "Fiat", Price = 1000000, ProductionYear = 2001, DoorsCount = 3, Accessories = new List<string>() { "Airbags"}, Owners = new List<string>() { "John Smith", "Ben Kovalsky" } };
This object is not very big, but has a lot of members that are irrelevant in some scenarios (ex. I don’t need a doors count when I am preparing a raport of the summary price of all the cars in the database). When we set the breakpoint after the above lines and press F5, debugger will show the following details of our ‘car’ object.
Clicking on these tiny arrows is irritating, don’t you think? I personaly hate it, especially when I’m in the rush, coding a hotfix or something ;).
Let’s assume, we want to show only Owners (as comma-separated string) and a car’s age (in the Car type we have only ProductionYear but we can calculate it, right?).
Creating proxy for debugging
First of all, we create a class responsible for displaying only the desired members:
internal class CarDebuggingView { private Car BaseCar { get; set; } public CarDebuggingView(Car car) { this.BaseCar = car; } public string Owners { get { return "Owners from proxy: " + String.Join(", ", this.BaseCar.Owners); } } public int Age { get { return DateTime.Now.Year - this.BaseCar.ProductionYear; } } }
As you can see, nothing sophisticated here ?. The class has a private object of the type we create proxy for and a constructor to initialize this object. We have also 2 public members – one to display comma-separated owners list and the other to show car’s age.
Ok, we created our proxy but what should we do with it?
Applying proxy for the apporopriate type
The answer is easy – apply it! We do it by adding attribute DebuggerTypeProxy to the appropriate type. Attribute’s first parameter should be our proxy type.
[DebuggerTypeProxy(typeof(CarDebuggingView))] public class Car : Vehicle { … }
And that’s it! You don’t have to do anything else! Please note, that there is no CarDebuggingView’s constructor’s literal calling! Attribute DebuggerTypeProxy makes compiler to do it for us. Pretty handy, don’t you think?
Below is the result of debugging the same ‘car’ object:
At the end of this post, I jsut want to mention that you can still access and display other members of Car while debugging. You will find them in the “Raw View” section.