Zev*_*itz 12 .net c# vb.net visual-studio .net-core
我正在为Visual Studio编写调试可视化程序,该可视化程序将表达式树呈现为C#或VB.NET伪代码。
我希望默认渲染语言应与当前调试窗口的语言匹配。
另外,我想添加功能以为表达式树中的给定节点生成Watch表达式;这需要知道当前正在调试哪种语言。
如何从可视化工具代码中检测当前正在调试的语言?
(我假设这对于任意运行时代码都是不可能的,因为代码已编译为IL。)
(项目发行)
感谢@dymanoid和@Homer Jay的最终版本是:
public enum SourceLanguage
{
Unknown, // probably C# for it's the only language without any particular symptom
VB,
FSharp,
Cpp
}
static class Extensions
{
private static readonly Dictionary<Assembly, SourceLanguage> cache = new Dictionary<Assembly, SourceLanguage>();
public static SourceLanguage GetSourceLanguage(this Type type) => type.Assembly.GetSourceLanguage();
public static SourceLanguage GetSourceLanguage(this Assembly assembly)
{
if (cache.TryGetValue(assembly, out var sourceLanguage))
return sourceLanguage;
var name = assembly.GetName().Name;
var resources = assembly.GetManifestResourceNames();
var assemblies = assembly.GetReferencedAssemblies().Select(a => a.Name);
var types = assembly.DefinedTypes;
if (assemblies.Contains("Microsoft.VisualBasic") &&
resources.Contains($"{name}.Resources.resources"))
sourceLanguage = SourceLanguage.VB;
else if (assemblies.Contains("FSharp.Core") &&
resources.Contains($"FSharpSignatureData.{name}") &&
resources.Contains($"FSharpOptimizationData.{name}"))
sourceLanguage = SourceLanguage.FSharp;
else if (types.Any(t => t.FullName.Contains("<CppImplementationDetails>.")))
sourceLanguage = SourceLanguage.Cpp;
else
sourceLanguage = SourceLanguage.Unknown;
cache[assembly] = sourceLanguage;
return sourceLanguage;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
如果一个人的类型CSType,VBType,FSType并CppType与创建C#,VB.NET,F#和C++/CLI分别
class Program
{
static readonly Dictionary<SourceLanguage, string> dict = new Dictionary<SourceLanguage, string>()
{
[SourceLanguage.Unknown] = "C#",
[SourceLanguage.VB] = "VB.NET",
[SourceLanguage.FSharp] = "F#",
[SourceLanguage.Cpp] = "C++/CLI"
};
static void Main(string[] args)
{
Console.WriteLine(string.Format($"Entry assembly source language: {dict[Assembly.GetEntryAssembly().GetSourceLanguage()]}"));
foreach (var t in new[] { typeof(CSType), typeof(VBType), typeof(FSType), typeof(CppType) })
Console.WriteLine($"{t.Name} source language: {dict[t.GetSourceLanguage()]}");
}
}
Run Code Online (Sandbox Code Playgroud)
结果变成
Entry assembly source language: C#
CSType source language: C#
VBType source language: VB.NET
FSType source language: F#
CppType source language: C++/CLI
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请参见编辑。
Visual Studio 自定义Visualizer API非常简洁。它没有提供任何方式来获取有关正在调试的代码的其他信息。
确实,您可以按照@Alex提出的方法进行操作。但是,有一些缺点。例如,您可能需要手动加载要调试的程序集(到临时文件夹中AppDomain)。此外,这种方式并不是真正可靠的方法,因为它完全允许C#中实现的Microsoft.VisualBasic程序集引用该程序集。
对于更通用,更安全的方法,可以使用Visual Studio Debugger API。
这是一个实现方法:
IDebugEventCallback2接口;Visual Studio调试器将使用IDebugEventCallback2.Event方法通知您的代码。IVsDebugger实例。IVsDebugger.AdviseDebugEventCallback提供IDebugEventCallback2实现的方法作为事件接收器。Event方法中,检查IDebugBreakpointEvent2-这是正在调试的进程到达断点的时间;您可能需要使用它QueryInterface进行检查-请参阅“呼叫者注意”。IDebugThread2实例获取IEnumDebugFrameInfo2对象,请参见IDebugThread2.EnumFrameInfo。IEnumDebugFrameInfo2.Next方法以获取FRAMEINFO结构。IDebugStackFrame2实例(m_pFrame字段),并使用其GetLanguageInfo方法获取在当前断点处实现代码的语言。很长一段时间,是的。但是绝对是(也许是唯一)可靠的。
尽管上面引用的Visual Studio Debugger API看起来像本机代码,但是您也可以轻松地在托管代码中使用它。该API基于COM,.NET平台完全支持它。您可以安装Visual Studio SDK,也可以只使用相应的NuGet包,例如Microsoft.VisualStudio.Debugger.Interop。通过添加这些程序包,您可以获得COM类型的托管包装,并且可以在代码中使用它们,就像它们是纯托管C#类型一样。
对于文档,请看一下Visual Studio调试器的可扩展性。您还可以在GitHub上查看Visual Studio SDK示例。
| 归档时间: |
|
| 查看次数: |
475 次 |
| 最近记录: |