Visual Studio如何从调试器中序列化对象

128

我正在尝试调查一个崩溃转储文件中的错误(因此无法更改代码)。我有一个非常复杂的对象(序列化表示中有数千行),它的状态不一致。为了调查其状态,Visual Studio调试器视图无用。但该对象有一个数据契约。我想将其序列化,然后使用我喜欢的文本编辑器浏览整个对象。是否可以在调试器中完成这个操作?


请注意,如果您有一些自定义容器类或其他类在调试过程中需要多次查看,但 IntelliSense 和 QuickView 无法识别它们,您可以为 VS 编写一个扩展程序来帮助在调试中显示您的自定义类。 - Csaba Toth
许多好的技巧也可以在这里找到:https://dev59.com/A3RC5IYBdhLWcg3wP-r5 - Josh
12个回答

245

如果你的应用程序域中已经存在 Json.Net,那么请将以下代码粘贴到你的立即窗口中:

Newtonsoft.Json.JsonConvert.SerializeObject(someVariable)


注意:此处包含 HTML 标签,请保留原样。

33
希望我能再次点赞这个回答,特别是相对于其他答案而言。 (抱歉,但我不想在我的职业生涯中看到另一行XML代码。) - yzorg
1
在一个非常长的测试调试会话之后,在我的程序写出成千上万个测试结果到文件之前,一个异常发生了。我在异常发生的断点处,仍然可以检查结果集合。这个技巧节省了我很多时间! - HAL9000
1
你可能需要在其他地方实际使用Json.Net,这样当你尝试在即时窗口中使用它时,它就会被加载(而不仅仅是添加引用)。 - Evan
1
我不得不使用Nuget添加Newtonsoft.Json包,并在我设置断点的方法中添加一行代码来创建一个虚拟的Newtonsoft.Json.JsonArrayAttribute()类以使其正常工作。这是一个非常出色的解决方案! - Richard Moore
4
这是一个好答案。我只做了微小的更改就使用它,以免去到美化程序的旅程。Newtonsoft.Json.JsonConvert.SerializeObject(someVariable,Newtonsoft.Json.Formatting.Indented) - Jamie
显示剩余4条评论

99

前段时间我写了这个一行代码,将对象序列化到磁盘上的文件中。将它复制/粘贴到你的Immediate窗口,并用你的对象替换obj(它被引用两次)。它会保存一个text.xml文件到c:\temp,根据你的需要进行更改。

(new System.Xml.Serialization.XmlSerializer(obj.GetType())).Serialize(new System.IO.StreamWriter(@"c:\temp\text.xml"), obj)

不要期望任何奇迹,如果对象无法被序列化,它会抛出异常。


4
这在立即窗口中对我有效。已点赞。 - Pankaj Kumar
1
当我在VS 2015的即时窗口中使用它时,我会得到这个“错误”: “不支持在此上下文中评估本机方法。” 有什么想法吗? - Vetras
当我运行它时,我收到以下消息:标识符“System”未定义 - Rasoul
有一个旧的VB.NET项目,必须这样放置,否则我会收到关于表达式语法的错误,如果有人需要:new System.Xml.Serialization.XmlSerializer(obj.GetType()).Serialize(New System.IO.StreamWriter("C:\temp\temp.txt"), obj) - Liquid Core
这太棒了。由于写入权限,我不得不使用不同的目录,但它像魔法一样运行。导入Excel后,甚至还很漂亮。 - Nando

40

5
那个链接似乎已经失效了,但是你可以在Visual Studio的“扩展和更新”对话框中搜索“Object Exporter”,并找到这个Github项目的地址在这里。顺便说一句,这个扩展很棒! - Niklas Söderberg
2
谢谢@Omar,这个想法很完美。但是它需要太长时间,在某些情况下会冻结。 - Wahid Bitar
1
同意@WahidBitar的观点-这是一个很棒的概念-非常适合设置单元测试数据,但扩展似乎相当有缺陷,并且在崩溃时会带走Visual Studio! - Dib
这确实是一个非常有用的工具。 - Ashutosh Singh
7
Visual Studio 2019 版本:如果您需要在 Visual Studio 2019 中使用 ObjectExporter,您可以按照以下步骤操作:
  1. 在 https://github.com/OmarElabd/ObjectExporter/releases 页面中下载 ObjectExporter 的最新版本。
  2. 打开 Visual Studio 2019 并创建一个新项目或打开现有项目。
  3. 在 Visual Studio 2019 中的“项目资源管理器”窗口中,右键单击您的项目并选择“管理 NuGet 包”。
  4. 在“NuGet 包管理器”窗口中,选择“浏览”选项卡,然后搜索“ObjectExporter”。
  5. 安装 ObjectExporter 并重新启动 Visual Studio。
  6. 现在您可以在代码中使用 ObjectExporter。
- MaciejLisCK
1
@OmarElabd,请问您能否将此发布为VS 2019和@022版本吗? - FoxDeploy

23

自从 .NET Core 3.0 版本,你可以使用 System.Text.Json

System.Text.Json.JsonSerializer.Serialize(obj)

15
在Visual Studio的"Immediate"窗口中使用以下内容,将c:\directory\file.json替换为您想要写入JSON的文件的完整路径,将myObject替换为您要序列化的变量:
System.IO.File.WriteAllText(@"c:\directory\file.json", Newtonsoft.Json.JsonConvert.SerializeObject(myObject))

5

Object Dumper是一个免费且开源的扩展程序,适用于Visual StudioVisual Studio Code

代码立即窗口中,"Dump as"命令可通过上下文菜单使用。

它可以将对象导出为:

  • C#对象初始化代码,
  • JSON,
  • Visual Basic对象初始化代码,
  • XML,
  • YAML。

我相信,结合Diff工具,这个工具会很有帮助。

我是这个工具的作者。


似乎是一个很棒的工具,但你是否计划推出 Python 版本? - geriwald
@geriwald 你是指 Visual Studio 的 IronPython 吗?它还在维护吗? - Yevhen Cherkes
好的,谢谢。如果有其他人想知道,解决方法是在输出终端中写入文件。 - geriwald
1
谢谢,伙计!这个扩展真的很有用! - fsbflavio
@fsbflavio,很高兴你觉得它有用。我看到你给我的Github存储库点了星。也谢谢你 :) - Yevhen Cherkes
显示剩余2条评论

3

我有一个常用的扩展方法:

public static void ToSerializedObjectForDebugging(this object o, FileInfo saveTo)
{
    Type t = o.GetType();
    XmlSerializer s = new XmlSerializer(t);
    using (FileStream fs = saveTo.Create())
    {
        s.Serialize(fs, o);
    }
}

我用一个字符串重载了它的saveTo方法,并从即时窗口中调用它:

public static void ToSerializedObjectForDebugging(this object o, string saveTo)
{
    ToSerializedObjectForDebugging(o, new FileInfo(saveTo));
}

3

你可以使用即时窗口对其进行序列化,然后将内容复制到你喜欢的编辑器中。

另一个选择是覆盖ToString()方法,并在调试模式下调用它。

你也可以在崩溃前不久将内容写入文件,或将代码包装成try/catch并在那时写入文件。我假设你能够确定何时出现崩溃。


谢谢,我尝试从“监视”窗口中执行相同操作,但它告诉我“函数评估需要所有线程运行”。使用“立即窗口”解决了这个问题。 - xvorsx

2
我一直在使用ObjectDumper.Net
它很好用,特别是如果你有实时单元测试。当一个测试运行时,我可以轻松地在控制台中查看变量的值,省去了手动调试的麻烦。
如果你正在使用XUnit,这个可能会有所帮助。

2

如果你遇到了循环引用的问题,请在立即窗口中运行以下代码:

最初的回答

Newtonsoft.Json.JsonConvert.SerializeObject(app, Newtonsoft.Json.Formatting.Indented,
new Newtonsoft.Json.JsonSerializerSettings
{
    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize
});

1
这是一个不错的示例,包含完整的命名空间是一个很大的优势。将“ReferenceLoopHandling.Serialize”更改为“ReferenceLoopHandling.Ignore”可能是许多情况下更快和“无错误”的替代方案。 - Furkan Ekinci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接