【问题标题】:Type information not correctly resolved by Roslyn Semantic ModelRoslyn 语义模型未正确解析类型信息
【发布时间】:2019-10-31 23:46:41
【问题描述】:

我无法使用 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 在未检索到实际类型时使用的默认值。

Dictionary 的定义应该来自 mscorlib。会不会是找不到?或者,我是否需要更改代码中的某些内容?显然它正在我同事的一台计算机上运行,​​但不是在我的计算机上运行。是配置.Net使用的问题吗?

【问题讨论】:

  • 你需要使用完整的类型名System.Collections.Generic.Dictionary&lt;string, string&gt;或者ausing语句
  • @Kalten 可能是正确的。您还可以使用 compilation.GetDiagnostics() 获取错误/警告,这样可以更轻松地找出问题所在。
  • 感谢您的建议。我错过了用于测试的 VB 代码不包含 Imports 语句的事实,所以即使我有对 mscorlib 的引用,命名空间也是未知的。在我添加命名空间前缀后它工作了。

标签: c# .net roslyn


【解决方案1】:

定义引用程序集不足以告诉编译器类名来自何处。您必须指定完整的类型名称 (System.Collections.Generic.Dictionary&lt;string, string&gt;) 或通过 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:程序不包含适合入口点的静态“Main”方法

是因为默认情况下编译器会尝试构建可执行文件而不是库。您可以使用 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);
}

【讨论】:

  • 我明白,这是有道理的。问题:如果我有一个完整的 C# 解决方案,这些信息(可执行文件与库)是否来自项目定义?我如何得到它?使用 MSBuild?
  • 我在答案底部添加了这个信息
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多