C# 如何比较Roslyn中不同项目的类型符号(ITypeSymble)?
我在解决方案中有两个测试项目。C# 如何比较Roslyn中不同项目的类型符号(ITypeSymble)?,c#,roslyn,roslyn-code-analysis,C#,Roslyn,Roslyn Code Analysis,我在解决方案中有两个测试项目。 第一个项目(“VDoc”)声明VDocQuery类型。 第二个项目(“VDocQueryTest”)调用VDocQuery构造函数。 我得到了两个VDocQuery的ITypeSymbol(每个项目一个),对其进行比较,但得到了错误的结果 步骤: 1.获取第一个ITypeSymbol(使用SemanticModel.LookupNamespacesAndTypes()方法从VDoc项目中获取)。 2.从VDocQueryTest项目(从ObjectCreation
第一个项目(“VDoc”)声明VDocQuery类型。
第二个项目(“VDocQueryTest”)调用VDocQuery构造函数。
我得到了两个VDocQuery的ITypeSymbol(每个项目一个),对其进行比较,但得到了错误的结果 步骤:
1.获取第一个ITypeSymbol(使用SemanticModel.LookupNamespacesAndTypes()方法从VDoc项目中获取)。
2.从VDocQueryTest项目(从ObjectCreationExpressionSyntax.GetTypeInfo().Type)获取第二个ITypeSymber
3.将其与ITypeSymble.Equals(ITypeSymble)进行比较 我期望的是真实的结果,但得到的是错误的结果 问题: 如何在一个解决方案中正确比较来自不同项目的ITypeSumbles? 代码示例:
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;
}
}
}
当您在VDocQueryTest项目中拥有对类型的引用时,获取ISymbol并将其传递给SymbolFinder.FindSourceDefinitionAsync()。这将实现它是来自另一个项目的元数据的符号,然后将该项目中的元数据符号交给您。从那里,您可以执行.Equals()。我可以通过在两个项目中使用不同的目标框架来重现您的问题。为两个项目设置相同的目标框架,然后原始解决方案将找到匹配的类型
如果您不能更改目标框架,那么您仍然可以比较
itypesymble.DeclaringSyntaxReferences
我在示例中添加了两行代码,结果是相同的-false:(var sVDocQuerySource=SymbolFinder.FindSourceDefinitionAsync(ti.Type,solution.result);bool result2=sVDocQuerySource.Equals(tVDocQuery);这太棒了。我尝试匹配一个符号BaseSymbol没有成功(暂且不提命名)使用我遇到此问题之前使用的一组符号。我刚刚尝试了您的原始解决方案和@Jason的修改,两种方法都正常工作。在这两种情况下,类型都是等效的。您使用的是哪个版本的Roslyn?您能以某种方式共享您的项目设置和引用吗?@Tamas,VS2015 Community Edition+Microsoft.Code.Analyzsis 1.0.0.0(使用nuget获取)。我可以发送最小解决方案。首先,我尝试从零开始创建最小解决方案,但无法重现问题。因此,在第二次尝试时,我复制真实解决方案并删除所有不必要的代码-问题被重现。框架是相同的-.NET Framework 4.5.2。以前的框架是4.5。但在运行测试前几天我更改了它。比较使用ISymbol.DeclaringSyntaxReferences很有效!谢谢。
using VDocQueryFunctionalTest;
namespace VDocQueryTest
{
static class VDocQueryUse
{
public static void VDocQueryUseTest()
{
new VDocQuery();
}
}
}