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

在 Linqpad 和 Visual Studio 之间架起桥梁 (结合 JSON 和扩展方法)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (16投票s)

2014年6月24日

CPOL

5分钟阅读

viewsIcon

43214

downloadIcon

189

这将允许您轻松地将 Linqpad 代码集成到 Visual Studio 中

下载文件包含两个项目和 Linqpad 示例代码。

引言

如果您还没有听说过 Linqpad,您应该 下载 它并试用一下。它是一个类似记事本的应用程序,可以让您快速编写 C# (VB, SQL, E# & F#) 代码,并即时编译运行。它在处理 Linq 方面非常有用,但我经常将其用作临时代码编辑器,每当需要快速测试一个假设或一些代码时。

别误会我的意思。我爱 VS,当我需要调试一些复杂的代码时,我第一个就会启动它,设置断点,并利用它提供的所有功能。但是,当我想要模拟一个对象或测试一个 Linq 表达式时,我通常不会启动 VS (半个 G 的内存占用,更长的加载时间,需要创建一个新项目,构建,编译,您懂的),而是会在 Linqpad 中完成。

Linqpad 我最喜欢的功能之一是 .Dump() 方法。它可以让您快速地将您正在处理的任何内容转储到屏幕上。字符串、对象、列表,应有尽有。作为额外的奖励,它还会返回对象,因此您也可以将其作为临时输出的延续,例如

var list = Enumerable.Range(1,6)
                     .Dump("list of six ints")
                     .Where(x=> x%2 ==0)
                     .Dump("only the pair ones")
                     .Select (x => x*3)
                     .Dump("selecting the pair ones times three");

将产生类似如下的结果

现在,有时我会遇到需要调用“大杀器”的时候。这通常涉及将我的 Linqpad 代码复制到现有解决方案,或创建一个新解决方案。这也不是什么大麻烦,但我需要手动删除所有 .Dump() 调用,或者将它们注释掉。

让我们看一个例子

这时,就轮到 巨龙 精灵 (Linqpad) 出场了

在本教程中,我将使用以下 Genie

class Genie{ 
    public Genie( int aYears     = 1000
                , int aWishCount = 3
                , string aColor  = "Blue"  )
    {
        YearsInTheBottle = aYears     ;
        WishesToGrant    = aWishCount ;
        Color            = aColor     ;
    }

    public int YearsInTheBottle { get; set; }
    public int WishesToGrant    { get; set; }
    public string Color         { get; set; }
    
    public void GrantWish(string aWish) {
        if ( WishesToGrant>0 ) 
        {
            Console.Out.WriteLine( "Your wish is my command." );
            Console.Out.WriteLine( "[{0}] granted.{1}"
                                 , aWish
                                 , Environment.NewLine    );
            WishesToGrant--;
            if (WishesToGrant==0) 
                Console.Out.WriteLine( "I'm finally freeeeeee...{0}"
                                     , Environment.NewLine);
        }
        else
            Console.Out.WriteLine("You're all out of wishes ...");
    }
}

如果您看过 《阿拉丁》,您应该知道我在说什么。如果没看过,那太遗憾了。快去看吧。

现在您可以将这段代码粘贴到 Linqpad 中 (在语言选项中选择 "C# program"),然后执行以下操作

void Main()
{
    var genie = new Genie().Dump();
    
    genie.GrantWish("I want to be smart");
    genie.GrantWish("I want to be a lumberjack");
    
    genie.Dump();
    
    genie.GrantWish("I want to be the king of Narnia");
    genie.GrantWish("I want to get more wishes");
    
    genie.Dump();
} 

结果将如下所示

好了,完成了!我已经测试了我的类,有了可视化输出,就可以继续我的下一个项目了。

传统的 Visual Studio 解决方案

常规步骤大致如下

  • 创建一个新的控制台解决方案
  • 将 Linqpad main 方法中的代码粘贴到您的控制台 main 方法中
  • 意识到您没有 .Dump()
  • Genie 类粘贴到您的解决方案中
  • 重写 ToString() 以便获得一些输出
        public override string ToString()
        {
            return string.Format( "YearsInBottle:{1}{0}WishesToGrant{2}{0}Color:{3}{0}"
                                , Environment.NewLine
                                , YearsInTheBottle
                                , WishesToGrant
                                , Color                                               );
        }
  • 将所有 genie.Dump() 更改为 Console.Out.WriteLine(genie);

恭喜!现在您可以运行您的项目,您将看到类似以下内容

《帝国》精灵反击战

一种解决方法是创建一个扩展方法来打印您的 Genie 对象。这种方法的缺点是它不是通用的,您需要为每个想要调试的类执行此操作。

您可以尝试从头开始编写 Dump() (或者也许请求作者提供代码),但这两种方法对我来说都太激进了。

您还可以使用反射来获取对象的所有属性及其值,处理一些特殊情况并自己格式化。缺点是通常的“反射很慢”,而且代码也不是最漂亮的 (是的,Newtonsoft 可能会这样做,但它已经写好、经过测试并针对性能进行了优化)。

这是另一个解决方案

1. 安装 NewtonSoft JSON

进入您的 Nuget 包管理器,安装 NewtonSoft JSON (您不必局限于版本 6,我相信现在已经发布了版本 10)。

2. 在您的控制台项目中创建一个名为 ExtensionMethods.cs 的新文件。

在这个文件中,我们将为 Dump() 方法添加我们的扩展方法。如果您觉得这有点过了,答案是否定的。它是模块化的,我通常会为特定项目需要其他扩展方法,所以它们都会在这个文件中愉快地共存。

您的文件应该如下所示

using System;
using Newtonsoft.Json;
 
namespace JSON_Dump
{
    public static class ExtensionMethods
    {
        /// <summary>
        /// This is a simple (and lazy, read: effective) solution. Simply send your
        /// object to Newtonsoft serialize method, with the indented formatting, and
        /// you have your own Dump() extension method.
        /// </summary>
        /// <typeparam name="T">The object Type</typeparam>
        /// <param name="anObject">The object to dump</param>
        /// <param name="aTitle">Optional, will print this before the dump.</param>
        /// <returns>The object as you passed it</returns>
        public static T Dump<T>(this T anObject, string aTitle = "")
        {
            var pretty_json = JsonConvert.SerializeObject( anObject, Formatting.Indented );
            if ( aTitle != "" )
                Console.Out.WriteLine( aTitle + ": " );
 
            Console.Out.WriteLine( pretty_json );
            return anObject;
        }     
    }
}

(我一直忘记从 VS 粘贴内容会保留格式…太棒了…)

所有这些都是接收一个对象 (我们不关心它的类型),将其交给 Newtonsoft.Json,然后问:“您能帮我把这个对象变得好看一点吗?”。Newtonsoft Json 会将您的对象转换为 JSON,然后为您缩进,完全免费。我们会将其输出到屏幕,并返回我们收到的对象,因此您仍然可以在上面的 示例 中使用它。

3. 继续使用您的 Linqpad 代码 (包括 .Dump())

现在您可以直接将 Linqpad 代码粘贴到您的 main 方法中,它就会正常工作。无需任何更改。 :)

粘贴并运行代码后的效果如下

如您所见,您会得到漂亮的 JSON 对象表示,它是缩进的,如果您有嵌套对象,它们会进一步缩进。

好消息

这很容易,而且不需要您付出太多努力。您可以直接将扩展文件粘贴到您的项目中,或者如果您愿意,您可以将所有常用的扩展方法编译成一个 DLL,然后直接引用它 (我就是这么做的,因为我有一些其他常用的绝妙扩展方法)。

坏消息

如果您还没有学到,生活中没有什么是免费的。您不必担心重写 ToString() 的好处,但您需要付出磁盘空间。Newtonsoft DLL (将被复制到您的输出文件夹) 大约 433kb,与之配套的 XML 还有 435kb。这不算什么大事,尤其是如果您已经在项目中使用 Newtonsoft JSON 进行其他操作,但如果您想发布一个小型可执行文件,您可能需要坚持重写 ToString()。 :)

总结

希望您觉得这很有用,即使没有,我也希望它能给您一些有趣的思考。

如果您想了解更多关于 Newtonsoft JSON 的信息,请访问 项目主页

如果您想了解更多关于扩展方法的信息,请访问此 MSDN 页面

如果您觉得这篇文章有帮助,请给文章投票,留下评论,并随时在此文章中回帖。 微笑 | :)

历史

  • 2014 年 6 月 24 日:首次发布
  • 2014 年 6 月 29 日:修复了锚点标签代码和一些格式问题
  • 2015 年 5 月 8 日:又一轮格式和阅读增强
  • 2017 年 9 月 29 日:修复了一个拼写错误并添加了另一个选项。
© . All rights reserved.