我遇到了这个问题,我肯定遗漏了一些东西。我已经设法将问题减少到可以在此处发布的可复制示例。
这段使用 Microsoft.CodeAnalysis.CSharp.SyntaxFactory 的示例代码
var compilationUnit = CompilationUnit()
.AddMembers(
NamespaceDeclaration(ParseName("TopNSpace"))
.AddMembers(
InterfaceDeclaration("IInterfaceUsing")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
PropertyDeclaration(IdentifierName("ChildNSpace.IInterfaceUsed"), "UsingProperty")
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
)
)
)
)
.AddMembers(
NamespaceDeclaration(ParseName("TopNSpace.ChildNSpace"))
.AddMembers(
InterfaceDeclaration("IInterfaceUsed")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
)
);
创建一个 CompilationUnitSyntax,在调用 NormalizeWhitespace().ToFullString() 时产生这个:
namespace TopNSpace
{
public interface IInterfaceUsing
{
ChildNSpace.IInterfaceUsed UsingProperty { get; }
}
}
namespace TopNSpace.ChildNSpace
{
public interface IInterfaceUsed
{
}
}
我的问题是,当我尝试直接从这个 CompilationUint 的 SyntaxTree 创建 CSharpCompilation 时,它会产生一个错误:
var compilationFailed = CSharpCompilation.Create("Fails")
.AddSyntaxTrees(compilationUnit.SyntaxTree) // Using SyntaxTree directly
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
以上会产生此诊断错误: 找不到类型或命名空间名称“ChildNSpace.IInterfaceUsed”(是否缺少 using 指令或程序集引用?)
但是如果我解析 CompilationUnit 的 ToString() 来创建一个新的语法树,它会起作用:
var tree = CSharpSyntaxTree.ParseText(compilationUnit.NormalizeWhitespace().ToFullString());
var compilationSucceeded = CSharpCompilation.Create("Succeeds")
.AddSyntaxTrees(tree) // Now from the re-parsed string
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
这工作正常,不会产生任何错误。
在这两种情况下,CSharpCompilation 的 LanguageVersion 都是 CSharp11。
我在这里错过了什么?我不应该能够直接从语法树创建 CSharpCompilation 吗?
在我的实际用例中,CompilationUnit 的语法树非常大,从 CompilationUnit.ToString() 解析新树时性能会受到显着影响。所以我真的很想避免它。
非常感谢任何帮助!
感谢 StackOverflow 成为橡皮鸭!发布问题后就想通了。
IdentifierName 在为 PropertyDeclationSyntax 指定点分类型时并不适用。符合要求的是 QualifiedNameSyntax。
从以下位置更改 PropertyDeclaration 的类型:
PropertyDeclaration(IdentifierName("ChildNSpace.IInterfaceUsed")
至:
PropertyDeclaration(QualifiedName(
IdentifierName("ChildNSpace"),
IdentifierName("IInterfaceUsed")
)
修好了!
是的,我觉得自己很蠢!我会在辩护中说,当检查从 ToString() 生成的代码时,它看起来完全一样。
生活和学习!