其他分享
首页 > 其他分享> > CodeGo.net>如何比较来自罗斯林不同项目的类型符号(ITypeSymbol)?

CodeGo.net>如何比较来自罗斯林不同项目的类型符号(ITypeSymbol)?

作者:互联网

我在解决方案中有2个测试项目.
第一个项目(“ VDoc”)声明VDocQuery类型.
第二个项目(“ VDocQueryTest”)调用VDocQuery构造函数.
我得到2个VDocQuery的ITypeSymbol(每个项目一个),将其进行比较,但得到错误的结果.

脚步:
1.获取第一个ITypeSymbol(从VDoc项目中使用SemanticModel.LookupNamespacesAndTypes()方法).
2.从VDocQueryTest项目中获取第二个ITypeSymbol(来自ObjectCreationExpressionSyntax.GetTypeInfo().Type)
3.将其与ITypeSymbol.Equals(ITypeSymbol)进行比较.

我希望得到正确的结果,但是得到错误的结果.

题:
如何在一个解决方案中正确比较来自不同项目的ITypeSymbols?

代码示例:

class Program
{
    static void Main(string[] args)
    {
        string solutionPath = @"..\..\..\StaticAnalysis.sln";

        MSBuildWorkspace workspace = MSBuildWorkspace.Create();
        Solution solution = workspace.OpenSolutionAsync(solutionPath).Result;

        var vdocProject = FindProjectByName("VDoc", solution);
        SemanticModel semanticModel = vdocProject.Documents.First().GetSemanticModelAsync().Result;
        var nsVDocQueryFunctionalTest = (INamespaceOrTypeSymbol)semanticModel.LookupNamespacesAndTypes(0, null, "VDocQueryFunctionalTest").First();
        var tVDocQuery = (ITypeSymbol)semanticModel.LookupNamespacesAndTypes(0, nsVDocQueryFunctionalTest, "VDocQuery").First();

        TypeInfo ti = GetFromVDocRef(solution);
        bool result1 = ti.Type.Equals(tVDocQuery); // false, expected = true?

        //these 2 lines added after Jason Malinowski answer
        var sVDocQuerySource = SymbolFinder.FindSourceDefinitionAsync(ti.Type, solution).Result;
        bool result2 = sVDocQuerySource.Equals(tVDocQuery); // false, expected = true?

       //this line solved the problem, thanks to @Tamas
       bool result3 = ti.Type.DeclaringSyntaxReferences.FirstOrDefault()?.Equals(tVDocQuery.DeclaringSyntaxReferences.FirstOrDefault()) ?? false;
    }

    private static TypeInfo GetFromVDocRef(Solution solution)
    {
        var vdocQueryTestProject = FindProjectByName("VDocQueryTest", solution);
        var vdocQueryTestProjectSemanticModel = vdocQueryTestProject.Documents.First().GetSemanticModelAsync().Result;
        var compilationUnit = (CompilationUnitSyntax)vdocQueryTestProject.Documents.First().GetSyntaxRootAsync().Result;
        var ns = (NamespaceDeclarationSyntax)compilationUnit.Members[0];
        var cls = (ClassDeclarationSyntax)ns.Members[0];
        var method = (MethodDeclarationSyntax)cls.Members[0];
        var stat = (ExpressionStatementSyntax)method.Body.Statements[0];
        var newExpr = (ObjectCreationExpressionSyntax)stat.Expression;
        var ti = vdocQueryTestProjectSemanticModel.GetTypeInfo(newExpr);
        return ti;
    }

    static Project FindProjectByName(string projectName, Solution solution)
    {
        var project = solution.Projects.SingleOrDefault(p => p.Name == projectName);
        return project;
    }
}

VDocQuery.cs:

using System.Collections.Generic;

namespace VDocQueryFunctionalTest
{
    public class VDocQuery
    {
        public VDocQuery()
        {
        }

        public void AddFields(string docType, params string[] fields)
        {
        }

        public List<VDoc> Execute()
        {
            return null;
        }
    }
}

VDocQueryUse.cs:

using VDocQueryFunctionalTest;

namespace VDocQueryTest
{
    static class VDocQueryUse
    {
        public static void VDocQueryUseTest()
        {
            new VDocQuery();
        }
    }
}

解决方法:

我可以通过在两个项目中使用不同的目标框架来重现您的问题.为两个项目设置相同的目标框架,然后您的原始解决方案将找到匹配的类型.

如果您不能更改目标框架,则仍可以比较ITypeSymbol.DeclaringSyntaxReferences.

标签:roslyn,roslyn-code-analysis,c
来源: https://codeday.me/bug/20191119/2036225.html