gpt4 book ai didi

c# - 实现缺失接口(interface)的 Roslyn 2.x CodeFix,委托(delegate)给成员,VS 2017

转载 作者:行者123 更新时间:2023-12-05 03:09:00 25 4
gpt4 key购买 nike

背景

我正在寻求创建一个 Roslyn CodeFix,它将响应来自 Visual Studio 附带的内置分析器的诊断警告,它将识别未实现或部分实现的接口(interface),从而允许我遍历丢失的接口(interface)成员,并生成自定义代码,将方法调用委托(delegate)给实现该接口(interface)的类型的成员字段。

(Visual Studio 附带的 Roslyn Analyzers 和 CodeFixes 确实提供了此功能,但我需要自定义和扩展代码的生成,这是不可能的,因为 Microsoft 实现都标记为 internal.)

请注意:接口(interface)几乎总是位于外部的第三方程序集中,我无权访问它的源代码。

例如开始于:

public class CustomDocumentDBClient : IDocumentClient
{
}

期望的结果将类似于以下内容(在实践中,一旦基本原则起作用,我将创建多个版本来添加额外的代码来包装方法调用):

public class CustomDocumentDBClient : IDocumentClient
{
// Field to which calls are delegated, initialised by the constructor
private readonly IDocumentClient _documentClientImplementation;

// Constructor
public CustomDocumentDBClient (IDocumentClient documentClientImplementation)
{
_documentClientImplementation = documentClientImplementation;
}

// Interface method that delegates to private field for invocation
public Task<ResourceResponse<Attachment>> CreateAttachmentAsync(string documentLink, object attachment, RequestOptions options = null)
{
return _documentClientImplementation.CreateAttachmentAsync(documentLink, attachment, options);
}

// Interface method that delegates to private field for invocation
public Task<ResourceResponse<Attachment>> CreateAttachmentAsync(string documentLink, Stream mediaStream, MediaOptions options = null, RequestOptions requestOptions = null)
{
return _documentClientImplementation.CreateAttachmentAsync(documentLink, mediaStream, options, requestOptions);
}
...
other methods
...
}

我尝试了什么

我花了一些时间阅读有关 Roslyn 的语法树和语义模型功能的教程。

我还检查了来自 GitHub 的 Roslyn 源代码——它确实包含了我希望实现的确切功能;然而,代码在各种复杂的类中交织在一起,并作为 internal 方法实现,不能被覆盖或扩展,甚至不能提取到独立项目中。

来自调查多个样本,以及一个相关的 SO 问题 How to see if a class has implemented the interface with Roslyn我得出的结论是,我必须使用 Roslyn 语义模型来获取有关接口(interface)及其声明成员的信息。

一旦我可以获得接口(interface)成员,我就可以使用 SyntaxFactory 构建所需的输出代码,并且我使用“Roslyn Quoter”作为指导。

从默认模板创建一个 CodeFix,响应正确的诊断代码很简单,而且它正在运行。

问题

我遇到的问题是采用诊断位置标识的 token ,它似乎是一个 SimpleBaseTypeSyntax token ,并且

  1. 验证它实际上代表一个接口(interface),
  2. 获取允许我枚举第三方接口(interface)成员的符号定义。

Syntax Visualizer 指示接口(interface)声明节点的类型为 SimpleBaseType

因此,我使用以下代码从语法树中获取 token 作为 SimpleBaseTypeSyntax-

    // Find the interface Syntax Token detected by the diagnostic.
var interfaceBaseTypeSyntax =
root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf()
.OfType<SimpleBaseTypeSyntax>().First();

a) 这确实会返回一个标记,其中包含语法树中相关节点的信息 - 但是,我看不到任何“InterfaceTypeSyntax”类型或 IsInterface 方法来验证它实际上是一个接口(interface)。

b) 我相信我应该能够使用 semanticModel.GetSymbolInfo(interfaceBaseTypeSyntax),但是这总是返回 null - 请记住接口(interface)是在外部程序集中声明的。

我需要做些什么才能通过 GetSymbolInfo 提供该信息,还是我应该采取另一种方法...?

非常感谢您的建议...

最佳答案

发了这么快就找到了,有点尴尬,不过解决办法好像是引用了Identifier这是 SimpleBaseTypeSyntax 的后代.

var interfaceSymbolInfo =
semanticModel.GetSymbolInfo(interfaceBaseTypeSyntax.DescendantNodes().First());

然后,通过调用:

var interfaceTypeInfo = 
semanticModel.GetTypeInfo(interfaceBaseTypeSyntax.DescendantNodes().First());

然后我可以使用 interfaceTypeInfo.Type.IsInterface验证我确实找到了接口(interface)类型,并且还访问了 interfaceTypeInfo.Type.GetMembers() .

通过语法可视化工具,答案就在眼前。

Syntax Visualizer

我暂时将此打开,以防其他人有更好的解决方案...谢谢!

关于c# - 实现缺失接口(interface)的 Roslyn 2.x CodeFix,委托(delegate)给成员,VS 2017,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44091647/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com