Introduction
Many a times, programmers want to execute a small code snippet to see the output of some simple calculations. They have to waste time creating a new project, writing the sample code and executing it on some form.
For instance, we want to check the output in the following cases:
-
int i = 2, j;
j = i * 3;
return j;
-
DateTime dt = new DateTime();
return dt;
The Problem
A simple solution to get the output is to code a macro that can compile just the code snippet and give you the solution, all in the same code window you are using now.
So, here is a list of requirements for the macro I can think of:
- It should display the value of a variable that is a result of a calculation or a simple code execution.
- A programmer doesn't have to create a new project/form. The programmer will just select the code snippet that he/she wants to execute.
- There must be some facility to include
namespace
s.
Using the Code
To solve the problem of execution of the code snippet, I use reflection. I also assume some custom keywords for identifying the return variable.
Following are the steps involved in the macro:
- Firstly, before compiling the code, we need to convert the code snippet into a complete class.
- Then we compile the code snippet. Report any errors directly from here.
- Then we create an object of the newly compiled class.
- Execute the dummy function containing the code snippet.
- Output the result to the Output Window. Here I assume that when we want to include any
namespace
in the compilation, we use the keyword using
. The keyword return
is used to identify the return variable.
Here, we have a snippet that picks up the user selected source code to execute.
For i As Integer = iStart To iEnd
ActiveDocument().Selection.GotoLine(i)
ActiveDocument().Selection.SelectLine()
If (ActiveDocument().Selection.Text.Trim().IndexOf("using") >= 0) Then
strUsing += ActiveDocument().Selection.Text.Trim()
ElseIf (ActiveDocument().Selection.Text.Trim().IndexOf("return") >= 0) Then
strReturn = ActiveDocument().Selection.Text.Trim().Replace(";", "") + _
".ToString();"
ElseIf (ActiveDocument().Selection.Text.Trim().IndexOf("refer") >= 0) Then
compilerOptions.ReferencedAssemblies.Add(ActiveDocument(). _
Selection.Text.Trim().Replace(";", "").Replace("refer", "").Trim())
Else
strSource += ActiveDocument().Selection.Text.Trim()
End If
Next
As seen in the above code snippet, we get the user selection and loop through all the lines. In case we find the two keywords, using
and return
, we make the appropriate settings. All other lines are considered as statements to be directly executed.
After this step, we compile the dummy code and make an object of the newly compiled class:
newAssembly = compilerResults.CompiledAssembly()
Dim objTypes() As Type = newAssembly.GetTypes()
Dim t As Type = newAssembly.GetType("TestNamespace.TestClass")
Dim obj As Object = Activator.CreateInstance(t)
Dim method As MethodInfo = t.GetMethod("TestMe")
owpane.OutputString("Output = " + method.Invoke(obj, Nothing))
We simply run the function and use the ToString()
method to get the text of the variable.
We also use a simple function to get a handle to the Output
window in Visual Studio where we display the output to the user.
Function GetOutputWindowPane(ByVal Name As String, _
Optional ByVal show As Boolean = True) As OutputWindowPane
Dim win As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
If show Then win.Visible = True
Dim ow As OutputWindow = win.Object
Dim owpane As OutputWindowPane
Try
owpane = ow.OutputWindowPanes.Item(Name)
Catch e As System.Exception
owpane = ow.OutputWindowPanes.Add(Name)
End Try
owpane.Activate()
Return owpane
End Function
Drawbacks
- Some major drawbacks in this macro are that it does not have much of error handling.
It only works for C# but can be easily modified to work for VB.NET too. - Complex objects cannot be calculated. e.g.
Datatable
, Dataset
.
Update History
- 27/09/2007: Posted the article (Code with lot of bugs:)
- 28/09/2007: Changed the files bundled in the Zip (Imports and common function added)