Roslyn语义模型未正确解析类型信息

问题描述 投票:0回答:1

我无法使用Roslyn的语义模型检索字段的类型信息。它适用于int或string等简单类型的字段,但不适用于Dictionary 。

这里是代码:

using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace SemanticsCS
{
    class Program
    {
        static void Main(string[] args)
        {
            var tree = CSharpSyntaxTree.ParseText(@"
            public class MyClass {
             int z;
             Dictionary<string, string> dict;
             int Method1() { int x = 3; return 0; }
             void Method2()
             {
                int x = Method1();
             }
        }
    }");
            // 
            Dictionary<string, string> dict;
            var Mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location);
            var compilation = CSharpCompilation.Create("MyCompilation",
                syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
            var model = compilation.GetSemanticModel(tree);

            //Looking at the first method symbol
            foreach (var nodeSyntax in tree.GetRoot().DescendantNodes())
                {
                var methodSymbol = model.GetSymbolInfo(nodeSyntax);
                var symbolInfo = model.GetSymbolInfo(nodeSyntax);
                var typeInfo = model.GetTypeInfo(nodeSyntax);

                if (typeInfo.Type != null)
                    Console.WriteLine(nodeSyntax.GetText() + ":" + typeInfo.Type.Kind);
            }
        }
    }
}

当我运行它时,我得到

             int :NamedType
             Dictionary<string, string> :ErrorType
string:NamedType
string:NamedType
                         int :NamedType
int :NamedType
3:NamedType
0:NamedType
                         void :NamedType
                                int :NamedType
Method1():NamedType

我认为ErrorType是Roslyn在未检索到实际类型时使用的默认值。

字典的定义应来自mscorlib。可能是找不到了吗?还是我需要更改代码中的某些内容?显然,它可以在我的同事的一台计算机上工作,但不能在我的计算机上工作。是否需要配置.Net的使用?

c# .net roslyn
1个回答
1
投票

定义引用程序集不足以告诉编译器类名的来源。您必须指定完整类型名称(System.Collections.Generic.Dictionary<string, string>)或通过using语句进行定义。

为了帮助您了解错误,您可以查看诊断报告。 (来自CSharpCompilation或SyntaxTree)。

foreach (var d in compilation.GetDiagnostics())
{
    Console.WriteLine(CSharpDiagnosticFormatter.Instance.Format(d));
}

它将给您这个:

(11,1): error CS1022: Type or namespace definition, or end-of-file expected
(4,10): error CS0246: The type or namespace name 'Dictionary<,>' could not be found (are you missing a using directive or an assembly reference?)
error CS5001: Program does not contain a static 'Main' method suitable for an entry point
(5,30): warning CS0219: The variable 'x' is assigned but its value is never used
(4,37): warning CS0169: The field 'MyClass.dict' is never used
(3,14): warning CS0169: The field 'MyClass.z' is never used

以下错误是名称空间错误。

((4,10):错误CS0246:找不到类型或名称空间名称'Dictionary '(您是否缺少using指令或程序集引用?)]

但是您可以看到那里还有其他。由于脚本末尾有多余的},因此出现以下内容。

((11,1):错误CS1022:类型或名称空间定义,或预期的文件结束]

结束最后一个:

错误CS5001:程序不包含适用于入口点的静态“主”方法

是因为,默认情况下,编译器尝试构建可执行文件而不是库文件。您可以使用OutputKind枚举更改它。

var compilation = CSharpCompilation.Create(
    "MyCompilation",
    syntaxTrees: new[] { tree },
    references: new[] { Mscorlib },
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

编辑:

如果要从现有的csproj文件中找到OutputKind,则可以这样操作:(受this gist的启发

// Nuget :
// https://www.nuget.org/packages/Microsoft.Build.Locator
// https://www.nuget.org/packages/Microsoft.CodeAnalysis.Workspaces.MSBuild/
// https://www.nuget.org/packages/Microsoft.CodeAnalysis

if (!MSBuildLocator.IsRegistered)
{
    MSBuildLocator.RegisterDefaults();
}
using(var wp = MSBuildWorkspace.Create()){
    var project = await wp.OpenProjectAsync(@"pathtocsprojfile.csproj");
    Console.WriteLine(project.CompilationOptions.OutputKind);
}
© www.soinside.com 2019 - 2024. All rights reserved.