Practical MVVM

Last Wednesday night, I attended a talk at RockNUG on MVVM by Joel Cochran.  It’s the best explanation of the Model-View-ViewModel design pattern that I’ve seen so far.  I found his talk particularly useful because he focused on the fundamentals of the design pattern instead of a specific framework (of which there are many).

Cochran’s talk was good for second and completely unexpected reason–his use of Mercurial for his code demos.  I’ve been to my share of conferences and user groups and seen a lot of demos, but before that talk, I’d never seen a speaker eliminate the inevitable typos and otherwise speed up his presentation that way.  When there was some code he wanted to show that exhibited an aspect of his Practical MVVM Manifesto, he simply grabbed a commit from his local Mercurial repository and updated the code in place.  The next time I give a talk or do any demos, I hope I can make good use of that trick too.

.NET Reflector–No Longer Free, But Still Worth It

Those of us who registered with red-gate.com after they bought Reflector from its creator, Lutz Roeder, got an e-mail on February 2 saying the next version of Reflector would no longer be free.  It’s the second time in my recent memory that a free and/or open source package for .NET became closed.  The first one was NCover, which was probably the best option out there for determining how much of your codebase was covered by unit tests.  Even at a price with subscription of $658, it may be a more cost-effective option than paying for the Visual Studio sku that includes team testing tools.

By contrast, the entry-level price for .NET Reflector is relatively low ($35).  As a tool, I think it’s valuable enough to the every-day .NET developer to spend their own money for.

Introducing .NET Reflector

I gave a presentation on .NET Reflector at the January 12 meeting of RockNUG.  I took most of my time demonstrating the product and answering questions, so I had very few slides.  So instead of simply posting them here and calling it a day, this blog post will incorporate some of the Q & A that happened during the presentation.

What Is It?

The title slide in my presentation called .NET Reflector an “x-ray machine for (unobfuscated) .NET assemblies”.  That little phrase actually understates what .NET Reflector can do.  Decompiling .NET assemblies is only one of the three major things it does (and is probably the best-publicized of its capabilities).  This tool also provides an excellent class browser and static analysis capabilities.

Why Is It Helpful?

In addition to giving developers to see code for third-party assemblies when they don’t have access to their source files, it can be quite a useful learning tool for seeing what the compiler generates on-the-fly for the source code we write ourselves.

Demos

One of the first features I demonstrated was the ability of .NET Reflector to decompile an assembly into multiple .NET languages.  C# is the default, but VB.NET, Delphi, Oxygene, MC++, F#, and MSIL are the other target languages available out of the box.  Using the add-in architecture of .NET Reflector, one developer added limited support for decompilation to PowerShell (download the PowerShellLanguage.zip file).

Around this point in the presentation, someone asked if you could cut-and-paste decompiled source into a file.  Not only does it work, but with Denis Bauer’s Reflector FileDissassembler plug-in installed, you can decompile an entire assembly into its constituent source code files (though I suspect that Red Gate Software would prefer that you pay for .NET Reflector Pro to get this capability). 

I was also able to demonstrate the much-overlooked static analysis capabilities of .NET Reflector.  They enable developers to learn what code depends on particular methods, where they’re used, what code exposes them, and where they’re called.  It turns out that there’s a free plug-in which extends this capability even further.  The Dependency Structure Matrix (DSM) plug-in allows developers to generate and manipulate matrices for determining the level of complexity in a software architecture.  Considering that a full-featured tool with DSM capability like NDepend costs hundreds of dollars per seat license, even a fraction of those features from a free .NET Reflector plug-in are well worth the time to learn how to leverage.

More Q & A

When I showed that .NET Reflector pulled in source code comments in its display of disassembled code, one member of the audience pointed out (correctly) that this was only possible because the XML file containing the comments was co-located with the assembly.  When I tested the disassembly capability afterwards without the XML file present, the comments didn’t display.

There was also a question from the audience about how .NET Reflector compared with ILDASM (which ships with the .NET Framework).  The short answer is that ILDASM is far more limited by comparison.  It only decompiles to IL, it lacks the analysis capabilities of .NET Reflector, and most importantly it doesn’t have a plug-in architecture to enable expansion of what it can do.

Conclusion

My presentation on January 12 only scratched the surface of what .NET Reflector can do.  I hope this post has added more depth, and piqued your curiosity to use the tool to improve your own development experience.  You may find the following links helpful in leveraging .NET Reflector for your own development work:

Deleting TFS Tasks

I changed the state of a TFS task I was working on recently, only to discover the workflow wouldn’t let me return it to it’s prior state.  Until today, I didn’t know it was possible to delete TFS tasks if you made a mistake in changing one.  But some Googling revealed a blog post that explained how to delete tasks.

The direction of the slashes for the URL can point forward (/) instead of backward () and the witadmin.exe destroywi /Collection:<TFS url> /id:<Task id> command still works.

Filtering Heterogeneous Arrays in .NET

One of the bugs I was recently asked to fix for an application required me to determine whether or not to display one of the members of a list.  This proved somewhat challenging since the lists in question were heterogeneous (two difference subtypes of an abstract base class).  It turned out that LINQ provides a nice solution to this sort of problem in the form of the OfType<T> method.

Given an IEnumerable collection with elements of multiple types, calling OfType<T> on the collection where T is the desired type will return a collection containing only elements of type T.  Before learning about OfType<T>, I’d been using the Cast<T> method.  This was fine as long as all the collection elements were of the type T I wanted.  The moment this wasn’t the case, my LINQ query threw a cast exception.  OfType<T> seems to work similarly to the “as” operator in C#, in that it doesn’t complain if a list element isn’t type T–it simply excludes it from the returned collection.

PowerGUI and .NET Framework 4.0

On my current project, we use PowerShell scripts to automate our UI testing.  We’ve been writing and running the scripts in the PowerGUI Script Editor, an excellent tool that’s also free.  When we upgraded our application to run on version 4.0 of the .NET Framework from 3.5, we lost the ability to run PowerShell scripts in debug mode from PowerGUI.

The only work-around for this I’ve found (at least until a version of PowerGUI built on .NET 4.0 comes out), is a registry hack that forces all the .NET apps on the machine to use the latest version of the CLR.  You can find more details in this user discussion at powergui.org, or this discussion on stackoverflow.com.

New MSBuild 4.0 Features

My current assignment has me working with the application build again.  MSBuild 4.0 got a number of new features which I’m only now getting to take advantage of.  The coolest one so far is the extensible task factory.  It lets you define custom MSBuild tasks right in the project file, instead of having to create a separate DLL for them.  Andrew Arnott wrote a custom factory that lets you define custom MSBuild tasks using PowerShell.  Because we’re using PowerShell for UI automation testing of our application, we’ll soon be able to integrate those tests into our build system.

Another feature I just learned about is conditional constructs.  They provide functionality equivalent to a case statement you might see in other languages. It’s much more flexible than the Condition attribute available on most MSBuild tasks.

ScrollViewer+ItemsControl vs. ListView

One of my most recent tasks at work was determining the cause of slow performance in one part of an application and coming up with a fix (if possible).  We tracked the source of the problem down to a use of ItemsControl inside a ScrollViewer.  Because the ItemsControl instance was trying to display hundreds of complex items, it took a noticeably long time to load.  This turns out to be a known issue, with a few possible solutions.  Simply changing the ItemsPanelTemplate of the ItemsControl instance to contain a VirtualizingStackPanel didn’t fix our performance problem.

What did resolve our performance issue was replacing the ScrollViewer and ItemsControl combination with a ListView.  The list of what we changed includes:

  • Giving the ListView the same name as the ItemsControl.
  • Giving the ListView the same ItemsSource as the ItemsControl.
  • Update the ItemsPanelTemplate of the ListView to use VirtualizingStackPanel.
  • Set HorizontalScrollBarVisibility to “Disabled”.
  • Bound the Visibility property of the ListView to a Converter.
  • Update the ItemContainerStyle with a ListViewItem style that sets the HighlightBrushKey and ControlBrushKey to be transparent.

Note: The last of those steps does override those styles for the entire application, so it may be best to skip it unless it doesn’t negatively impact the look-and-feel of the rest of your application.

The changes we made reduced the load time from around 20 seconds down to less than 2 seconds for 400 items.

The tradeoff in moving to a ListView (with VirtualizingStackPanel) from ScrollViewer+ItemsControl is scrolling speed.  Scrolling through 400 items does go more slowly, but it’s preferable to waiting as long as we did just to see the data.

My First PowerShell Cmdlet

We’ve been using PowerShell to write automated tests of the UI on my current project.  One of the tasks I took on today was creating a custom cmdlet to enable us to select radio buttons.

I already had an existing assembly of cmdlets to work with, so I just added a new class (SelectRadioButton) to it.  Next, I added references to System.Management.Automation and System.Windows.Automation. With these references in place, I could add this attribute to the class:

[Cmdlet(VerbsCommon.Select, "RadioButton", SupportsShouldProcess = true)]

The attribute determines the actual name of the cmdlet you’ll use in scripts (Select-Radiobutton).  The cmdlet needs an instance of AutomationElement to operate on, so that’s defined next:

[Parameter(Position = 0, Mandatory = true, HelpMessage = "Element containing a radio button control")]
[ValidateNotNull]
public AutomationElement Element { get; set;}

Finally, I adapted some of the logic for my override of the ProcessRecord from this article on using UI automation.  The end result looks something like this:

protected override void ProcessRecord()
{
try
{
if (Element.Current.ControlType.Equals(ControlType.RadioButton))
{
SelectionItemPattern pattern = Element.GetCurrentPattern(SelectionItemPattern.Patern) as SelectionItemPattern;
if (pattern != null) pattern.Select();
}
else
{
//Put something in here for handling something other than a RadioButton
}
}
catch (Exception ex)
{
// You could put some logging here
throw;
}

}

When default settings attack

When you first install SQL Server 2008 Express, the TCP/IP protocol is disabled by default.  Be sure the protocol is enabled (which requires restarting the service) before you try to run an application that depends on it, otherwise you could spend hours trying to figure out why your application won’t work.  It looks like SQL Server 2008 R2 Developer behaves the same way.

I suggested this awhile back to a co-worker who’d been struggling all day with why an application wasn’t working, and it turned out to be the solution.