Roslyn - 编译简单类:“找不到类型或命名空间名称 'string'..."

问题描述:

我正在使用 Roslyn API 来生成和编译一个类.生成的类如下所示:

I'm using the Roslyn API to generate and compile a class. The generated class looks like this:

namespace MyCompany.Product
{
    public class TestClass
    {
        public void Configure(string id)
        {
        }
    }
}

然而,当我编译它时,Emit(ted) 结果给出:

However, when i come to compile it, the Emit(ted) result gives:

错误 CS0246:找不到类型或命名空间名称字符串"(您是否缺少 using 指令或程序集引用?)

error CS0246: The type or namespace name 'string' could not be found (are you missing a using directive or an assembly reference?)

这是执行编译的方法:

    private static readonly IEnumerable<string> DefaultNamespaces = new[]
        {
            "System",
            "System.IO",
            "System.Net",
            "System.Linq",
            "System.Text",
            "System.Text.RegularExpressions",
            "System.Collections.Generic"
        };

    public void Compile(IEnumerable<SyntaxTree> syntaxes, string targetPath)
    {

        var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
        // assemblyPath = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"

        IEnumerable<MetadataReference> defaultReferences = new[]
        {
            MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "mscorlib.dll")),
            MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll")),
            MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Core.dll")),
            MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),

        };
        CSharpCompilationOptions defaultCompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                    .WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release)
                    .WithUsings(DefaultNamespaces);

        CSharpCompilation compilation = CSharpCompilation.Create(
            targetPath,
            syntaxTrees: syntaxes,
            references: defaultReferences,
            options: defaultCompilationOptions);

        using (var ms = new MemoryStream())
        {
            EmitResult result = compilation.Emit(ms);
            // here, result.Success = false, with it's Diagnostics collection containing the error
            if (!result.Success)
            {
            } 
        }
    }

但是,如果我编译下面的类,但使用类型为string"的常量,它会按预期编译,因此当声明为方法参数类型时,它不喜欢string":

However, if I compile the below class, but using a constant of type 'string', it compiles as expected, so it doesn't like 'string' when declared as a method parameter type:

namespace MyCompany.Product
{
    public class TestClass
    {
        public const string Id = "e1a64bdc-936d-47d9-aa10-e8634cdd7070";
    }
}

我使用的是框架 4.6.1,Microsoft.CodeAnalysis 版本=1.3.1.0

I'm using framework 4.6.1, Microsoft.CodeAnalysis Version=1.3.1.0

我将您的第一个示例片段输入 CSharpSyntaxTree.ParseText 并将结果输入 Compile - 它编译成功正如预期的那样.

I fed your first example snippet into CSharpSyntaxTree.ParseText and the result into Compile - it compiled successfully as expected.

我的猜测是您正在编译的节点类型有问题.string 是一个 C# 关键字,它是 System.String 类型的别名,它本身并不是一个类型名称.

My guess is that the node type that you're compiling is somehow wrong. string is a C# keyword that aliases the System.String type and is not a type name per se.

您可以使用 Roslyn Syntax Visualizer 来检查您自己的 SyntaxTreeCSharpSyntaxTree.ParseText 从预期输出中生成的差异.

You can use the Roslyn Syntax Visualizer to check for differences between your own SyntaxTree and one generated by CSharpSyntaxTree.ParseText from the expected output.