65.9K
CodeProject 正在变化。 阅读更多。
Home

Visual Studio 2003 的 C# 代码运行宏

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (4投票s)

2007年9月26日

CPOL

2分钟阅读

viewsIcon

32840

downloadIcon

126

使用此宏,您可以检查代码片段的输出,而无需创建新的项目/窗体。您可以直接在当前代码窗口中执行此操作。

引言

很多时候,程序员想要执行一小段代码来查看一些简单计算的输出。他们不得不浪费时间创建一个新项目,编写示例代码并在某个窗体上执行它。

例如,我们想在以下情况下检查输出

  1. int i = 2, j; 
    j = i * 3; 
    return j; 
  2. DateTime dt = new DateTime();
    return dt;

问题

获得输出的一个简单解决方案是编写一个宏,它可以编译代码片段并为您提供解决方案,全部在您现在使用的同一代码窗口中。

因此,这是我能想到的宏的要求列表

  1. 它应该显示作为计算结果或简单代码执行结果的变量的值。
  2. 程序员不必创建新的项目/窗体。程序员只需选择他/她想要执行的代码片段。
  3. 必须有一些包含 namespace 的工具。
Screenshot - UsageSample1.jpg

Using the Code

为了解决代码片段的执行问题,我使用了反射。我还假设一些自定义关键字来识别返回变量。

以下是宏中涉及的步骤

  1. 首先,在编译代码之前,我们需要将代码片段转换为一个完整的类。
  2. 然后我们编译代码片段。直接从这里报告任何错误。
  3. 然后我们创建一个新编译的类的对象。
  4. 执行包含代码片段的虚拟函数。
  5. 将结果输出到输出窗口。在这里,我假设当我们想要在编译中包含任何 namespace 时,我们使用关键字 using。关键字 return 用于识别返回变量。

在这里,我们有一个代码片段,它拾取用户选择的源代码来执行。

'Check if any special using is used in code
        For i As Integer = iStart To iEnd

            ActiveDocument().Selection.GotoLine(i)
            ActiveDocument().Selection.SelectLine()

            'Check if the user wants to include some special namespace
            If (ActiveDocument().Selection.Text.Trim().IndexOf("using") >= 0) Then

                'add the assembly to the future code
                strUsing += ActiveDocument().Selection.Text.Trim()
            ElseIf (ActiveDocument().Selection.Text.Trim().IndexOf("return") >= 0) Then

                'Set the return string for the function
                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

                'else add it as source
                strSource += ActiveDocument().Selection.Text.Trim()

            End If

        Next

如上面的代码片段所示,我们获取用户选择并循环遍历所有行。如果我们找到两个关键字, usingreturn,我们进行适当的设置。所有其他行都被认为是直接执行的语句。

在此步骤之后,我们编译虚拟代码并创建一个新编译的类的对象

'Get the Assembly from the compiled code
        newAssembly = compilerResults.CompiledAssembly()

        'Get the method and call it
        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")

        'Call the output of the method
        owpane.OutputString("Output = " + method.Invoke(obj, Nothing))    

我们只需运行该函数并使用 ToString() 方法来获取变量的文本。

我们还使用一个简单的函数来获取 Visual Studio 中 Output 窗口的句柄,我们在其中向用户显示输出。

    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

缺点

  • 这个宏的一些主要缺点是它没有太多的错误处理。
    它只适用于 C#,但可以很容易地修改为也适用于 VB.NET。
  • 无法计算复杂的对象。例如 Datatable, Dataset

更新历史

  • 2007 年 9 月 27 日:发表文章(包含大量错误的程序代码:)
  • 2007 年 9 月 28 日:更改了 Zip 中捆绑的文件(添加了 Imports 和常用函数)
© . All rights reserved.