Sooner or later I'm going to stop writing these simple tutorials and put some better content out here ... but until then, here is a simple walk through of creating a Reflector addin that will count the number of box instructions used in a method.
The majority of the code is the standard addin glue (IPackage implementation and a command button with event handler) ... things I'm sure you've seen before. Somethings that you might not have seen before:
- Adding the command button to the context menu for a method declaration by adding to the "Browser.MethodDeclaration" command bar
- Using the AssemblyBrowser's ActiveItem property to get the item that is currently selected in the AssemblyBrowser (tree view)
- Searching through a method's instructions for a specific IL instruction (in this case 0x8c for box)
In order to get this simple addin working, here is all you need to do:
- Create a new dll project and name it something like "BoxCount"
- Set a reference to Reflector.exe
- Set a reference to System.Windows.Forms
- Paste the following in your class code and compile:
using System;
using Reflector;
using Reflector.CodeModel;
using System.Windows.Forms;
namespace Reflector.Addin
{ public class BoxCountPackage : IPackage
{ private ICommandBarManager commandBarManager;
private ICommandBarSeparator separator;
private ICommandBarButton button;
private IAssemblyBrowser assemblyBrowser;
public void Load(IServiceProvider serviceProvider)
{ this.assemblyBrowser = (IAssemblyBrowser)serviceProvider.GetService(typeof(IAssemblyBrowser));
this.commandBarManager = (ICommandBarManager)serviceProvider.GetService(typeof(ICommandBarManager));
this.separator = this.commandBarManager.CommandBars["Browser.MethodDeclaration"].Items.AddSeparator();
this.button = this.commandBarManager.CommandBars["Browser.MethodDeclaration"].Items.AddButton("Count Box Instructions", new EventHandler(this.Button_Click));
}
public void Unload()
{ this.commandBarManager.CommandBars["Browser.MethodDeclaration"].Items.Remove(this.button);
this.commandBarManager.CommandBars["Browser.MethodDeclaration"].Items.Remove(this.separator);
}
private void Button_Click(object sender, EventArgs e)
{ IMethodDeclaration methodDef = this.assemblyBrowser.ActiveItem as IMethodDeclaration;
if (methodDef != null)
{ ShowBoxCount(methodDef);
}
}
private void ShowBoxCount(IMethodDeclaration methodDef)
{ string message = string.Format("{0} box instructions found.", GetBoxCount(methodDef)); MessageBox.Show(message);
}
private int GetBoxCount(IMethodDeclaration methodDef)
{ int boxCount = 0;
IMethodBody methodBody = methodDef.Body as IMethodBody;
if (methodBody != null)
{ foreach (IInstruction instruction in methodBody.Instructions)
{ if (instruction.Value != null && instruction.Code == 0x8c)
{ boxCount++;
}
}
}
return boxCount;
}
}
}
Once you have the addin built and added to your Reflector (View->Add-ins...) you need to test it.
Create a Console app with the following code and compile:
using System;
namespace Boxing
{ class Program
{ static void Main(string[] args)
{ int i = 2;
int i2 = 4;
Console.WriteLine(i + " test");
Console.WriteLine(i + " test" + i2);
}
}
}
If you look at the IL code generated by for the sample app it looks something like this (note it has 3 box instructions):
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] int32 i,
[1] int32 i2)
L_0000: nop
L_0001: ldc.i4.2
L_0002: stloc.0
L_0003: ldc.i4.4
L_0004: stloc.1
L_0005: ldloc.0
L_0006: box int32
L_000b: ldstr " test"
L_0010: call string [mscorlib]System.String::Concat(object, object)
L_0015: call void [mscorlib]System.Console::WriteLine(string)
L_001a: nop
L_001b: ldloc.0
L_001c: box int32
L_0021: ldstr " test"
L_0026: ldloc.1
L_0027: box int32
L_002c: call string [mscorlib]System.String::Concat(object, object, object)
L_0031: call void [mscorlib]System.Console::WriteLine(string)
L_0036: nop
L_0037: ret
}
If you add the sample console app to the assembly browser in Reflector and right click on the Main method you should have a context menu item of "Count Box Instructions" like shown below:
When you click on the menu item, you should now get a message box like the following:
Now you have a simple addin that will count the box instructions in a method for you.