如何比较 Microsoft.CodeAnalysis.ITypeSymbol 和 System.Type
How to compare a Microsoft.CodeAnalysis.ITypeSymbol to a System.Type
我已经成功地从 SyntaxNode 接收到一个 ITypeSymbol,方法是:
SemanticModel.GetTypeInfo(sytaxNode).ConvertedType
现在我想知道这个 ITypeSymbol
是否对应于我的执行代码中存在的 System.Type
实例,例如 typeof(IEnumerable<int>)
或 someObject.GetType()
。
我试过了
typeInfo.ConvertedType.ToString() == type.ToString()
但是它们不使用相同的格式规则,例如像 IEnumerable<int>
这样的泛型
TypeInfo.ToString() == "System.Collections.Generic.IEnumerable<int>"
同时
typeof(IEnumerable<int>).ToString() == "System.Collections.Generic.IEnumerable`1[System.Int32]"
此外,我认为最好比较 AssemblyQualifiedNames 而不是仅比较命名空间和类型名称,以避免可能的名称冲突。
理想情况下,我希望能够在我的执行代码中获得实际的 System.Type 实例,该实例与我从语义模型中获得的 ITypeInfo 相对应(前提是已加载所需的程序集 and/or可用的)。这将允许检查该类型是否可从其他类型等分配。
您可以使用 Compilation.GetTypeByMetadataName()
.
获取类型名称的 INamedTypeSymbol
所以试试这个:
semanticModel.GetTypeInfo(sytaxNode).ConvertedType.Equals(
semanticModel.Compilation.GetTypeByMetadataName(typeof(WhateverType).FullName))
这不适用于封闭泛型类型,对于那些你需要做更多的事情。例如:
var ienumerableType = semanticModel.Compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1");
var intType = semanticModel.Compilation.GetTypeByMetadataName("System.Int32");
var type = ienumerableType.Construct(intType);
根据@Tamas 的回答,我创建了以下适用于封闭泛型类型的递归解决方案。
static bool TypeSymbolMatchesType(ITypeSymbol typeSymbol, Type type, SemanticModel semanticModel)
{
return GetTypeSymbolForType(type, semanticModel).Equals(typeSymbol);
}
static INamedTypeSymbol GetTypeSymbolForType(Type type, SemanticModel semanticModel)
{
if (!type.IsConstructedGenericType)
{
return semanticModel.Compilation.GetTypeByMetadataName(type.FullName);
}
// get all typeInfo's for the Type arguments
var typeArgumentsTypeInfos = type.GenericTypeArguments.Select(a => GetTypeSymbolForType(a, semanticModel));
var openType = type.GetGenericTypeDefinition();
var typeSymbol = semanticModel.Compilation.GetTypeByMetadataName(openType.FullName);
return typeSymbol.Construct(typeArgumentsTypeInfos.ToArray<ITypeSymbol>());
}
我已经成功地从 SyntaxNode 接收到一个 ITypeSymbol,方法是:
SemanticModel.GetTypeInfo(sytaxNode).ConvertedType
现在我想知道这个 ITypeSymbol
是否对应于我的执行代码中存在的 System.Type
实例,例如 typeof(IEnumerable<int>)
或 someObject.GetType()
。
我试过了
typeInfo.ConvertedType.ToString() == type.ToString()
但是它们不使用相同的格式规则,例如像 IEnumerable<int>
TypeInfo.ToString() == "System.Collections.Generic.IEnumerable<int>"
同时
typeof(IEnumerable<int>).ToString() == "System.Collections.Generic.IEnumerable`1[System.Int32]"
此外,我认为最好比较 AssemblyQualifiedNames 而不是仅比较命名空间和类型名称,以避免可能的名称冲突。
理想情况下,我希望能够在我的执行代码中获得实际的 System.Type 实例,该实例与我从语义模型中获得的 ITypeInfo 相对应(前提是已加载所需的程序集 and/or可用的)。这将允许检查该类型是否可从其他类型等分配。
您可以使用 Compilation.GetTypeByMetadataName()
.
INamedTypeSymbol
所以试试这个:
semanticModel.GetTypeInfo(sytaxNode).ConvertedType.Equals(
semanticModel.Compilation.GetTypeByMetadataName(typeof(WhateverType).FullName))
这不适用于封闭泛型类型,对于那些你需要做更多的事情。例如:
var ienumerableType = semanticModel.Compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1");
var intType = semanticModel.Compilation.GetTypeByMetadataName("System.Int32");
var type = ienumerableType.Construct(intType);
根据@Tamas 的回答,我创建了以下适用于封闭泛型类型的递归解决方案。
static bool TypeSymbolMatchesType(ITypeSymbol typeSymbol, Type type, SemanticModel semanticModel)
{
return GetTypeSymbolForType(type, semanticModel).Equals(typeSymbol);
}
static INamedTypeSymbol GetTypeSymbolForType(Type type, SemanticModel semanticModel)
{
if (!type.IsConstructedGenericType)
{
return semanticModel.Compilation.GetTypeByMetadataName(type.FullName);
}
// get all typeInfo's for the Type arguments
var typeArgumentsTypeInfos = type.GenericTypeArguments.Select(a => GetTypeSymbolForType(a, semanticModel));
var openType = type.GetGenericTypeDefinition();
var typeSymbol = semanticModel.Compilation.GetTypeByMetadataName(openType.FullName);
return typeSymbol.Construct(typeArgumentsTypeInfos.ToArray<ITypeSymbol>());
}