Click here to monitor SSC
  • Av rating:
  • Total votes: 3
  • Total comments: 0
Michael Sorens

.NET Reflector Through the Looking Glass: The Cheese Course

21 January 2013

Part 4 describes how you can extend reflector further by describing how reflector can be used to compare or manage assemblies and exercise the code in front of you or even any arbitrary code on the fly.

Contents

Part 4: Extending Reflector Further

Part 1 of this series guided you through selecting an edition of .NET Reflector, installing it, and getting started with both the Reflector Desktop and the Visual Studio plugin. This article begins a comprehensive exploration of the key features of .NET Reflector, both natively and with enhancements provided by add-ins developed by the active Reflector community.

Part 2 covers the “meat and potatoes”, i.e. viewing, filtering, navigating, and debugging. Part 3 goes further into analyzing and exploring assemblies, showing you how to “slice and dice” to get to what you need. Part 4 rounds out the review of features explaining how to exercise the code in front of you or even any arbitrary code on the fly, as well as comparing and managing assemblies. The final part is a one-page companion wallchart that summarizes every feature in parts 2 through 4 and illustrates the key points of navigation in Reflector.

Browse Assemblies

Reflector Desktop: You can load any assemblies you wish, be they from the .NET framework, third-party assemblies, or your own. These all appear in the assembly browser which uses the traditional tree-structured organization for its contents. You can select and expand any node and walk the tree to whatever depth you need, going from assembly to namespace to type to member. Of course, the more assemblies you put in the list the more cluttered it gets and the bigger the memory footprint. Reflector allows you to manage multiple assembly lists to reduce this burden and to give you greater organizational control. By default all the assemblies you add are in the default assembly list. To add a new list, open the assembly list manager from menu (File >> Open Assembly List…) or keyboard (Ctrl+L). Here (see Figure 1) you can add a new list (select Add then enter a name), remove an existing list (select one then choose Remove), or switch to an existing list (select a list and press Select). Note that you cannot delete the default list—the Remove button is disabled.

Assembly list manager

Figure 1 The assembly list manager dialog lets you switch among existing assembly lists, as well as add or delete lists.

When you select a different list and close the assembly list manager, your assembly browser is refreshed with the contents of the newly chosen list. If you had switched to a new, empty list, the assembly browser is completely empty, so Reflector prompts you—as it did when you first launched the program with an empty default list—to select a version of the .NET framework to load. You can pick one or skip it if you do not need the framework assemblies loaded.

One more option for managing multiple assemblies is Reflector’s zip-file-awareness. When you access the Open Assembly dialog (File >> Open Assembly or Ctrl+O), you can open not just DLL and EXE files, but also ZIP files. So you can have another level of visual separation within the assembly browser.

VS Extension: Within VS you are typically not interested in arbitrary assemblies but rather just those that are associated with your project. The .NET Reflector object browser lists all the assemblies referenced in your project, also using the traditional tree-structured organization for its contents. You can drill down through any of the assemblies listed.

Exercise Assemblies

Reflector Desktop: With the SmokeTest add-in from Wesley Steiner you can actually execute portions of your API directly within .NET Reflector. You can construct an instance, call a method and get or set a property or field of any class then view or "drill-down" into the result without ever writing a single line of code. Originally designed as a standalone application, SmokeTest is now also available as a Reflector add-in. Steiner wrote this .NET Smoke Test for Reflector post that gives a quick walk-through of how to use it within Reflector.

Once you install the add-in—see the discussion under Extending Reflector—you will actually not see any new menu or context menu entries. Rather, you simply select a smoke-testable type in the assembly browser and a Smoke-Test panel will open automatically. As Steiner explains, a type is smoke-testable if it meets these criteria:

  • Must be a class or struct.
  • Must be neither generic nor an interface.
  • Must have all supporting DLLs and resources.

(Also wanted to mention that Steiner provides great support—while preparing this article I found a small bug and he turned around a new version for me in just a couple days!)

Execute Code Snippets

Reflector Desktop: As a complement to the SmokeTest add-in to run code from your assemblies—see Exercise Assemblies—Jason Haley’s Snippy add-in allows you to run arbitrarycode on the fly! Snippy serves another purpose as well: there are a variety of constructs in C# that are actually syntactic sugar, syntactic conveniences that actually are translated into a more raw syntax before being compiled. Snippy lets you peek under the hood and see this translated code as shown in Figure 2. The input code is in the Snippy panel (lower right); Snippy saves it, compiles it into the body of the canonical Main method of a standalone program in a temporary assembly (SnippyTempOutput.dll), then loads that into Reflector as any other assembly. Selecting the Main method yields the decompiled results in Reflector’s decompiled code panel (upper right).

snippy add-in in Relfector

Figure 2 The Snippy add-in lets you execute arbitrary code on the fly.

The above decompilation was targeted to .NET 4 so it comes out the other end quite similar. But if you use the target framework dropdown in Reflector’s toolbar to switch to .NET 2, for example, you get very different looking code (Figure 3).

decompiled code

Figure 3 The decompiled code from Figure 2, done with .NET 4.0) has been regenerated for .NET 2.0 here.

Note that Snippy by default compiles to a class library—notice the SnippyTempOutput.dll in the assembly tree in Figure 2. As such, you can build (compile) but you cannot execute because DLLs are not directly executable; the Start button remains disabled. Change Snippy’s output type (Tools >> Options >> Snippy >> Output Type) from Class library to Executable, though, to enable the Start button and you can execute your snippets as well. The option panel is also where you put references that you will often need to get your code to compile.

Compare Assemblies

Reflector Desktop: Sean Hederman’s Reflector Diff lets you do visual differencing of two assemblies just as you can do with text files using any of the popular text differencing tools (e.g. WinMerge, etc.). Once you install the add-in—see the discussion under Extending Reflector—you will have a new menu entry (Tools >> Assembly Diff). To use it, first select a source assembly at its root in the assembly browser (Point 1 in Figure 4). This displays the standard, top-level assembly information (Point 2). Open the Assembly Diff panel from the Tools menu and select the Browse button in the panel to bring a standard open file dialog to the fore. Find your target assembly and open it. The top-level assembly information for your target assembly loads in the Assembly Diff panel (Point 3).

Reflector Diff add-in

Figure 4 The Reflector Diff add-in provides a convenient way to compare minute differences in assemblies.

Typically the two assemblies you are comparing should differ in version number so your first difference between assemblies should appear immediately just as in the figure, where the source assembly displays version 1.1.0.0 and the target assembly displays 1.0.0.0. That’s helpful to help you keep track of which is which, but of course the real reason for comparing assemblies is to inspect differences lower down, either in a method implementation or a property or other code construct. This Assembly Diff add-in is ideal if you know the specific item you wish to examine. That would typically be the case if you, for example, have loaded a new version of a third-party library but are seeing different results from some method x. Simply drill down to that method in the assembly browser and Assembly Diffwill reveal the specific code differences, if any. Unfortunately, Assembly Diff does not provide either a single comprehensive view to browse all the differences or a way to navigate among the set of differences as is typical with text file differencing tools. (When I mentioned this to Hederman, he was receptive to the idea so some type of mechanism to move between differences may show up in a future version!)

Meta-query Assemblies

Reflector Desktop: When I sit down with any kind of data explorer, one of the first things I like to do is run meta-queries on the data. With a database, for example, I want to find out things like: How many tables actually contain data, i.e. how many are not empty? Which ones contain identity columns? Which tables include a column called IdAccount? And so forth.

With Reflector, the questions are more like this:

  • What properties does a given type have?
  • Which types have a Dispose method?
  • How many types are defined for each namespace in a given assembly?
  • What exceptions are thrown and by what methods for a given type?

list of meta-queries

Figure 5 List of meta-queries provided by Query Editor add-in.

Jason Haley’s PowerCommands add-in lets you execute queries to answer the above questions. This Query Editor is one of the dormant add-ins in the PowerCommands collection—see Add-In Collections: PowerCommands for how to activate it.Once you do, you will have two new entries in your Tools menu: Query Editor (which you use to open the query editor for general use) and Run Query (which lets you run a saved query showing you just the result). The query editor has both input and output panels, as you might expect. You can load a query in the input panel; executing it produces results in the output panel. If you just use the Run Query menu command, though, you do not see the input panel at all, just the results (which is often just what you want).

The Query Editor includes a large library of queries ready to be run, listed in Figure 5. To instantiate that list of queries just press the large Extract Sample Queries button in the PowerCommands options panel (Tools >> Options >> PowerCommands). They will be stored under your Documents folder (…\Documents\Reflector\Queries) and be immediately available in Reflector.

Each query is targeted for a specific type of object. You run a query by first selecting some object in the Reflector’s assembly browser then pressing the Start button in the Query Editor. If you attempt to run a query targeted at a different object type, it fails with the message “ActiveItem not valid for Query Type” in the output panel. You cannot necessarily tell just from looking at a query expression what is its query type. (Indeed, you cannot even tell what query you are looking at after you load it—the query name is not displayed anywhere, which would be useful.) But there is an easy way to see the query type—just press the Configuration button on the editor’s toolbar to reveal it. A query targeting a type (class) shows Type for its Query Type(yes, the word Type is unfortunately overloaded here!). A query targeting an assembly shows Assembly. Those set to AssemblyManager allow you to find out something across all loaded assemblies.

This add-in can do some useful work for you but it comes with a caveat: some functionality is lacking. In particular, you cannot modify any existing queries or build new ones. Since Red Gate acquired the PowerCommands they have been integrating them into the main product over time, as explained in the linked reference above. Given time, I am hoping this add-in may also make its way to the front line!

Add-In Collections

PowerCommands

This collection of add-ins by Jason Haley is one of the most comprehensive and most longstanding of all those for Reflector. It was introduced in 2009, though the members of the collection had apparently been around independently before then. In 2011, Red Gate acquired the collection and integrated it directly into .NET Reflector. The dust settled by late 2012 with the release of .NET Reflector 7.7, where Red Gate chose to include some of the PowerCommands as fully integrated out-of-the-box (see 7.7’s Power(ful) Commands)and to include others as dormant, which you could activate on demand.

Some of the integrated PowerCommands are discussed as full-fledged features in this series; the remaining ones playing a supporting role are discussed in the linked article given above.

The dormant ones are listed in the table. Each of these may be activated with a simple, two-step process. The first step (which is a one-time operation) is to install the PowerCommands.dll as an add-in like any other—see the discussion under Extending Reflector—using the preloaded PowerCommands.dll in the Addins folder in your Reflector installation directory. This materializes a new sub-panel in Reflector’s Options panel. The second step then is to open this sub-panel (Tools >> Options >> PowerCommands) and select or deselect the individual add-ins of interest.

Name

Description

Access

Bit Flag Converter

With this mini-bit flag calculator you can get an integer representation of a combination of bit flags simply by checking them off, or the converse: enter an integer and see which flags are lit up.

Context menu of enumerations having the [Flags] attribute. Example: System.Data.CommandBehavior

Create Binding Redirect

Generates an XML fragment to place in your program’s config file to redirect an assembly binding reference to a different version.

Context menu of assembly root node.

Enum Viewer

You can change the order of an enum sequence (by name or by value) and you can change the base (decimal or hex) in which the values are displayed by adjusting settings in Reflector’s Options panel.

Context menu of enumerations. Example: System.Data.CommandBehavior

Query Editor

Use LINQ to create meta-queries and interrogate your assemblies

Tools >> Query Editor opens the editor proper allowing selecting any query or writing new ones.
Tools >> Run Query just executes a selected query and provides results.

Table 1 Dormant add-ins included with the PowerCommands collection. Note that the Query Editor is discussed in a separate section.

(I did not include the Bookmarks add-in in the table that you will find on the options page because—as far as I can tell—the bookmark capability is fully installed without requiring the optional add-in.)

Assembly Visualizer

The Assembly Visualizer add-in collection from Denis Markelov provides several graphical perspectives above and beyond Reflector’s native capability to display various lists of dependencies for a single assembly at a time—see View dependencies (text list). This add-in collection provides a great perspective of multiple assemblies at once. Once you install the add-in—see the discussion under Extending Reflector—you will have several new context menu entries to access different views provided by Assembly Visualizer. (Note that this add-in collection has an additional installation constraint—the DLL must be located in the same directory as the Reflector executable itself.) The table lists the individual add-ins, what they display, and where to access them. You can access all of them from the context menu of an appropriate node in Reflector’s assembly browser.

Name

Description

Menu Access

View Access

Browse Assembly

Enhanced search capability including refinement by sorting criteria, visibility selection, and type categories.

Context menu of assembly root node.

  --

Browse Dependencies*

Display dependencies among assemblies.

Context menu of assembly root node.

  --

Browse Ancestry*

Display base class inheritance chain (with methods and properties) for a given type.

Context menu of types or enums. Example: System.DateTime

down arrow

Visualize Descendants*

Display all types derived from a given type.

Context menu of types or enums. Example: System.Data.DataException

right-arrow

Browse Interactions

Display interactions between members of one or more types.

Context menu of types or enums. Example: System.DateTime

settings icon

Table 2 Assembly Visualizer’s add-in collection. The starred items are discussed in detail: see the View Dependencies (graph), View Ancestry, and View Type Hierarchy topics.

For the three visualizations related to types specifically, you can also access them from within some of the other views (Browse Assembly, Browse Ancestry, Visualize Descendants) by clicking the graphical button shown in that view. As an example, the Browse Assembly window (Figure 6) shows that, when you hover over an item in the list, graphical buttons appear at the right end of the row showing you available views. (The blue arrow, not listed in the table above, navigates you to that item in Reflector’s main window.)

Assembly Visualizer browser

Figure 6 Assembly Visualizer’s assembly browser reveals jump buttons when you hover over an item in the list; the set of buttons varies depending on the item selected.

(Markelov wanted me to mention that this add-in is open source and seeking contributors!)

Conclusion

.NET Reflector is a great tool for exploring foreign code, but there is one case to mention where it is not strictly needed: examining or debugging code of the .NET framework itself. The MSDN article How to: Debug .NET Framework Source explains how to set options in Visual Studio to use its native ability (since VS 2010) to debug the framework.

Reflector hasn’t been standing still, though. The upcoming release (version 8) has some important new functionality: stepping into disabled call stack frames; when debugging an attached process Reflector populates its object browser with that process’s assemblies; new search capability in the object browser. See the Reflector blog to keep tabs on further progress.

It is in the nature of a developer to have a love/hate relationship with foreign code. It is a great time saver to just plug in a module rather than have to write it yourself. But all too frequently you come up with a use case that was not quite anticipated by its authors. At those times .NET Reflector is indispensable: no more guessing, no more trial and error—simply step into the suspect code to see what you need to adjust in the parameters you are supplying to the call.

Michael Sorens

Author profile:

Michael Sorens is passionate about software to be more productive, evidenced by his open source libraries in several languages (see his API bookshelf) as well as SqlDiffFramework (a DB comparison tool for heterogeneous systems including SQL Server, Oracle, and MySql). With degrees in computer science and engineering he has worked the gamut of companies from Fortune 500 firms to Silicon Valley startups over the last 25 years or so. Current passions include PowerShell, .NET, SQL, and XML technologies (see his full brand page). Spreading the seeds of good design wherever possible, he enjoys sharing knowledge via writing (see his full list of articles), teaching, and StackOverflow. Like what you have read? Connect with Michael on LinkedIn and Google +

Search for other articles by Michael Sorens

Rate this article:   Avg rating: from a total of 3 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.
 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.