Simple Talk is now part of the Redgate Community hub - find out why

‘Methodist’: Make .NET Reflector come alive with IronPython

It is great to be able to inspect the contents of an assembly with .NET Reflector, but to really understand the behaviour of code, it is nice to be able to call methods and see the results immediately within .NET Reflector. Now you can, thanks to the magic of IronPython and the DLR. Ben builds a REPL add-in for .NET Reflector and makes a great tool even more useful.

Anyone who has used .NET Reflector  knows what an amazing application it is! Being able to disassemble .Net objects into C# code: wow! Whereas it is useful to see the code, you can’t always fully understand the behaviour of code just from inspection. Wouldn’t it be great if you could see the code, and then initialize and interact with the object, calling methods and seeing the result directly within .NET Reflector?  Thanks to the Dynamic Language Runtime (DLR) and IronPython – you can!

This article will outline the functionality of a new add-in component called ‘Methodist‘ that I’ve written, and will describe the advantages it beings to .NET Reflector. The article will then discuss the technical details of the add-in and show how it was made possible.


Methodist’ plugs into the .NET Reflector infrastructure list like any other of its’ add-ins, while, at the same time, hosting the DLR. This  allows the use of the Python language against objects loaded into the  .NET Reflector assembly browser.

The DLR is a new platform from Microsoft which is gaining a lot of well-deserved attention. The platform sits on top of the CLR and is designed to allow dynamic languages to be implemented within the .Net platform. This enables them to interact with everything that .net has to offer while at the same time allowing applications, such as .NET Reflector, to embed the platform and take advantage of the capabilities offered by dynamic languages.

Dynamic languages themselves are on the increase. Many different languages, such as JavaScript, Ruby and Python fall into the dynamic category. Each of these languages offers something different, but they all share in common the principle that everything is determined at runtime, whereas with static languages like C# almost everything is determined at compile time in order to make the language  more flexible.  A Dynamic Language REPL allows us to execute code as we type it. This means we no longer need to write code, compile, load and execute in order to see the result. Dynamic languages evaluate everything at runtime, so that the world the language knows about,  such as the methods that exist on objects, the accessible objects or the libraries that are loaded, can change. Because of this, you can adapt the lifecycle to your needs and circumstances. Dynamic languages also tend to be more readable. Because they infer a lot from the code, there is much less ‘noise’ required than other languages: For example, there is no need to define a type for a variable as this is simply inferred at execution. The result is easier to type and read code.

The DLR makes it possible to implement dynamic languages on top of the .Net framework that can then interop with .Net objects and assemblies in exactly the same way they would with their native objects and libraries. For me, this combines the best of both worlds: For others this means they don’t need to learn a new coding style and set of libraries.

We can take advantage of all of this via .NET Reflector.

Installing “Methodist”

To run “Methodist”, first make sure you have the current version of Reflector installed. To install “Methodist”, download the DEBUG.ZIP from the bottom of the article, and copy the following files to the directory in wehich you installed Reflector.

  • IronPython.dll
  • IronPython.Modules.dll
  • Microsoft.Scripting.Core.dll
  • Microsoft.Scripting.dll
  • Microsoft.Scripting.ExtensionAttribute.dll
  • TheMethodist.dll

Start Reflector. Then click on the view->Addins menu and click on the Add button. In the dialog box that appears, select TheMethodist.DLL, and then close the dialog box. To see the methodist pane, click Cntl D. or use the tools menu

Using ‘Methodist’

As you can see from the screenshot below, the add-in simply plugs into .NET Reflector and provides the user with a command style prompt to start typing and executing code (a REPL).


 Fig 1 The Command-style prompt

By way of an example, we can do simple things such as add numbers together. While the code looks easily, under the covers the code goes via the IronPython implementation, converted into the correct representation for the DLR before being passed to the CLR as Intermediate Language (IL) for execution. The result is 2, which is being displayed on screen.


Fig 2: First steps for the REPL

Yet the implementation provides more than just this. Within the .NET Reflector Assembly Browser we have various standard .Net 3.5 assemblies loaded.  Because they are already loaded into .NET Reflector, our Methodist add-in has already detected and loaded them into its own process.

We can now start creating instances of objects. System.Windows.Forms is the main assembly for WinForms, the UI framework for .Net 2.0. From our Methodist add-in , we can create and interact with a new Window, clicking buttons and causing events to fire.


Fig 3: Hello world!

This demonstrates how flexible you can be with IronPython and how you can use it to interact with .Net. However, the fact we have embedded the application into .NET Reflector makes this more useful. 

As I mentioned in the introduction, seeing the code is only part of the process when we want to understand what it does. In reality, the best way to learn how the object works is to actually use it. For example, Path has a number of really useful methods. Yet, understanding what they do just from the code is difficult. With the help of the  ‘Methodist’ add-in , we can interact with the Path object in a live environment and see what they actually do and the results they return.


fig 4: Ooh! Executing code within .NET Reflector!

This is a great way to understand how the objects work. The same concept can be applied to testing different inputs and seeing how the method behaves. A method I occasionally use is ExpandEnvironmentVariables, this takes a Environment variable such as %TEMP% and expands it to be the actual path. To ensure I am using the method correctly, I can use the ‘Methodist’ add-in with some different inputs to verify that my expectations about how the method behaves are correct.


Fig 5: Ah, so that is what the method does

By being able to interact with methods, it becomes much quicker to learn new frameworks and methods, but there are times when we cannot access a method or property because it is private or marked as internal. C# allows you to use reflection to gain access to these methods, but it can be a case of trail and error to find the correct property to use. With IronPython, together with the correct flags, this is not an issue. Take the DLRReflector.Sample assembly. The TestObj class has three methods, 1 public, 1 internal, and 1 private. With ‘Methodist’ add-in , we can create an instance of the object as normal.

We can then inspect the methods on the object using the dir command. This provides us with a list of all the methods we can call on the object.  Two of the methods listed are internal and private prefixed with the object name.  Now we know the names, we can call and interact with them like normal.

This is very useful if you really want to understand the implementation of the object.


Fig 6: ‘… useful if you really want to understand the implementation of the object’

Hopefully you can see how powerful having the DLR and .NET Reflector together can be. We can combine the power of .NET Reflector and being able to see the code with the ability to actually construct and interact with the objects – all from the same application!

How we built ‘Methodist’

With the feature set in mind, we’ll now dive into the implementation and see how it was all put together. For an overview of Reflector add-ins, I recommend you read Andrew Clarke’s article (


Like with all Reflector extensions, we need an object which implements IPackage. This is the starting point for our add-in with the Load() method being the first method called by Reflector. The package is responsible for initialising our interaction with the DLR, creating the window, menu items and finally loading the assemblies into the DLR itself.

The initialisation of the Window is the main part of within our Load method. This allows users to display the add-in and start typing code. The first object required is the DLRHost, this is the object which is responsible for our hosting the DLR within our add-in.

We provide this object as a parameter to our ConsoleWindowManager. This knows how to construct our user control and add a menu item to the toolbar. 

In order to be able to display a window within Reflector, we need to register the window with the WindowManager.  This is done by accessing the IWindowManager service via the ServiceProvider and adding a new instance of our window, which is a simple WinForms UserControl.

Adding an item to the toolbar is done in a similar fashion via the ICommandBarManager service. The code below will add a separator together with a new button with the name Methodist under the Tools menu item. We have also attached a shortcut key of Ctrl+D.


When the menu item is clicked, or the shortcut key used, the DisplayConsoleWindow method is called. This simply sets the Visiblity of our Window to true.

The next stage of our DLRPackage is the ability to load the assemblies. The idea is that when you load an into Reflector, it is automatically loaded into the DLR runtime. However, Reflector also automatically has a set of assemblies loaded on startup which we will also need to load into DLR Addin on initialisation. This is done by simply iterating around the Asssemblies from the AssemblyManager and then loading them into the DLR via the Load method.

The loading process is executed on separate thread so we don’t lock our UI. Based on the Reflector assembly object, IAssembly, we need to expand the path for the assembly’s location as Reflector provides the path as ‘%SystemRoot%\\Framework\v2.0.50727\mscorlib.dll’.

Once we have the correct path, we load it into the appdomain, and then into the engine runtime.

To be able to continue to load in assemblies as and when the user does, we hook into Reflector’s AssemblyManager AssemblyLoaded event.

We then follow a similar process, we loop around the assemblies and if we can’t already loaded it then we call the above method. This allows users to load in new assemblies into Reflector and automatically have access to them from the Methodist.

We now have our Console Window and we have our assemblies being loaded. In order to load the assemblies, we needed an IronPython Engine. This engine was created by the DLRHost object.


Our DLRHost object is responsible for hosting the DLR and the execution of IronPython code. To create the engine we ask the Python object to provide one for us.

We then need to create a ScriptScope object which will store our variables, methods and objects created.

In order to execute code, we have an Execute method which takes a string as a parameter. We then need to create a ScriptSource object via the CreateScriptSourceFromString method and provide the code string as a parameter. We can then use this object to execute our code, providing it with the scope to use.

Our DLRHost can now execute IronPython code. However, we still need to provide a way to accept code from the user and know when to execute it. This is the role of the ConsoleWindow.


The ConsoleWindow is our UserControl which we added as a window via our ConsoleWindowManager.  The fundamental role is to take input from the user via a textbox. When the user presses enter, the code should be executed. The communication between the window and the DLRHost is done via an event which is fired when the enter key is pressed.


While we can execute code, the implementation is far from complete. The first task after being able to execute code is to redirect the output.

Redirect Out

When executing code, the user can cause data to be outputted to either the standard output or the standard error output. For example, in C#, when you use the Console.Writeline() method the data is simply wrote to the StandardOutput. As it happens in a console application this is the command prompt.

This method is called from our ConsoleWindow and as an argument a TextBoxWriter object is passed in. TextBoxWriter object inherits from TextWriter, however everything which is wrote to the stream is actually wrote out to the TextBox and as such our add-in instead. 


At the moment, users can enter a single line of code and have it executed. This is fine for executing code such as 1+1, however if we want to define methods like our buttonClicked event then we need support for entering multiple lines of code.

To allow this, there is the concept of continuations. When the user enters code we need detect if they have only entered part of a statement. If they have, we need to prompt them to enter more code before we can execute.

To detect if the code is incomplete, we can access the Code Properties on the ScriptSource object.

The result of the CodeProperties is a ScriptCodeParseResult. The GetCodeProperties method parses the code and then returns a result saying if the code is complete, invalid, or partially complete.  

When it comes to the execution, we use this method to determine if we should prompt the user to enter additional code. If we should, then we set a flag and write out a continuation marker in the UI – this is the ‘.’ you can see in the screenshots above.

When we execute the code again, we add the newly entered snippet to what we already know about and see if it is complete. If it is, we execute normally.; If not we prompt for more code.

This section of code allows users to define their own methods to use during execution.


To allow access to internal and private methods and members, we need to set the PrivateBinding flag.

Setting engine flags needs to be done when you initialised the Engine. In our DLRHost constructor, we change the code to pass in the options as a property dictionary.

When the engine is created, it will take these options into account and enable PrivateBinding allowing us to access the private methods.

Context Menu on Namespaces

Finally, after developing the add-in and using it in my day-to-day development I decided I wanted an easier way to import namespaces. Thankfully, Reflector allows us to extend the context menu based on the type of object the user clicked on.  This means we can add a new context menu onto our namespaces but leave the other objects untouched.

The AddContextMenu adds the item, when the user clicks the menu item the importIntoDLR method is called.

This method obtains the AssemblyBrowser, this allows us to determine which item is currently selected. Because we know this can only be called on Namespaces items we can cast the selected item to an INamespace and pass it to the ConsoleWindow object to write out the import statement.

While it is a simple change, it speeds up the process of interacting with objects.


‘Methodist’ is a new add-in for Reflector. It allows you to interact with objects within the live environment of Reflector. By hosting the DLR and providing you with the ability to write IronPython code, I feel this takes what is already great able reflector and extends it to add a new dimension and set of capabilities.

We would love to hear your comments on this, please leave them below.

How you log in to Simple Talk has changed

We now use Redgate ID (RGID). If you already have an RGID, we’ll try to match it to your account. If not, we’ll create one for you and connect it.

This won’t sign you up to anything or add you to any mailing lists. You can see our full privacy policy here.


Simple Talk now uses Redgate ID

If you already have a Redgate ID (RGID), sign in using your existing RGID credentials. If not, you can create one on the next screen.

This won’t sign you up to anything or add you to any mailing lists. You can see our full privacy policy here.