It's no secret that a big fan of LINQPad. Though I originally started out using it for data manipulation and visualisation in a previous life, over time my LINQPad queries have become more and more sophisticated, with high levels of interactivity and extensive use of LINQPad's layout and helper functions (some examples of more gratuitous LINQPad queries at the end of this post). LINQPad comes with sophisticated interactivity feaures - particularly since the new control suite introduced in 5.3, which gives you familiar desktop controls (textbox, radio buttons, combos, sliders etc.) with events that you can use to react to changes. Still, often I find myself wanting to quickly add a small amount of interactivity to a query without being too bothered about looks, typically in order to expose basic configuration-like functionality. After having rolled many basic configuration editors for different queries, each with varying levels of quality and capability, I decided to take a stab at putting together something a little more general purpose - the result was DumpEditable.
DumpEditable is essentially a property editor extension that lets you dump an editable representation of an object to the results view, so that you can then modify it interactively and respond to changes in your query. In the spirit of LINQPad's own
DumpEditable is available on all objects (with various caveats that I am still exploring), and returns the original object - so can be chained or placed in the middle of a pipeline. The idea is that for many basic cases, what DumpEditable gives you out of the box will be 'good enough', letting you get interactivity 'for free' and allowing you to focus on writing query logic. For example, here's the output you get from dumping a basic POCO with a range of properties including strings, numbers, dates, enums and booleans:
Pretty cool, right? Without writing any special code, we got a fully editable implementation of our
Pet, including reasonable handling of enums, nullable booleans and the collection of strings. Because it's handy to work with anonymous types in LINQPad, DumpEditable works with those too, and even allows them to be modified - something you can't do from C# code generally.
If your query has a main loop (like all the gratuituous examples) you can read updated values in the loop body. Otherwise, you'll probably want to be notified when changes are made to your object. You can do this by taking a reference to the
EditableDumpContainer that is created by DumpEditable (which is available as an
out parameter of
DumpEditable) and using one of the three change notification methods it provides to be notified of updates.
Whilst DumpEditable aims to play in the 'near enough is good enough' space - giving you cheap interactivity with low to no fuss - I have tried to design it with extensibility in mind. Internally, DumpEditable uses the (poorly named?) concept of
EditorRules to determine how to present an editable version of an object. An
EditorRule consists of a
match function, which returns true if the rule should be used for a given property, and a
getEditor function, which returns the content (the 'editor') that should be rendered by LINQPad proper for matching properties. As a user of DumpEditable you can add your own
EditorRules, and these will take precedence over any exisiting ones. Writing one from scratch looks something like this: There are a few helpers in the library to make adding your own editors easier, many are covered in the README and demonstrated in the built-in samples, including the slider control:
Cool! How can I use it?
You can install DumpEditable via NuGet: DumpEditable.LINQPad. DumpEditable comes with samples that will automatically be added to your LINQPad samples pane. There's also more documentation at the Github repo. The focus of DumpEditable to date has been centered on my own use caes, so if you think Im missing something that should be handled by DumpEditable, please let me know on GitHub. Happy Editing!
Bonus: Gratuitous uses of LINQPad
Below are a few clips of some wilder LINQPad queries I've put together: