如何将Roslyn语义模型返回的类型符号名称与Mono.Cecil返回的类型符号名称进行匹配? [英] How to match type symbol names as returned by Roslyn semantic model to those returned by Mono.Cecil?
问题描述
我有以下代码:
var paramDeclType = m_semanticModel.GetTypeInfo(paramDecl.Type).Type;
paramDeclType.ToString()
返回的位置
System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>
我也从Mono.Cecil获得了相同的信息- paramDef.ParameterType.FullName
返回
I also have the same information from Mono.Cecil - paramDef.ParameterType.FullName
returns
System.Collections.Generic.Dictionary`2<System.String,System.Collections.Generic.List`1<System.Int32>>
我想比较来自这两个不同来源的类型名称.
I would like to compare the type names coming from these two different sources.
如果可能,我想避免进行详尽的正则表达式解析.
I would like to avoid elaborate regex parsing, if possible.
欢迎想法.
P.S.
同时,我将寻找Microsoft的 Mono.Cecil
替代品-System.Reflection.Metadata.也许Microsoft的两个库可以产生兼容的类型名称.
In the meantime, I am going to look for Mono.Cecil
replacement from Microsoft - System.Reflection.Metadata. Maybe two libraries from Microsoft would be able to produce compatible type names.
推荐答案
我想分享我当前使用的功能:
I would like to share the function I currently use:
private const string GENERIC_ARG_COUNT_PATTERN = @"`\d+";
private static readonly Regex s_genericArgCountRegex = new Regex(GENERIC_ARG_COUNT_PATTERN);
public static bool IsSameType(this TypeReference typeRef, ITypeSymbol typeSymbol, bool isByRef)
{
if (isByRef || typeRef.IsByReference)
{
return isByRef && typeRef.IsByReference && DoIsSameType(((ByReferenceType)typeRef).ElementType, typeSymbol);
}
return DoIsSameType(typeRef, typeSymbol);
static bool DoIsSameType(TypeReference typeRef, ITypeSymbol typeSymbol)
{
var arrayTypeSymbol = typeSymbol as IArrayTypeSymbol;
var arrayTypeRef = typeRef as ArrayType;
if (arrayTypeSymbol != null || arrayTypeRef != null)
{
return arrayTypeSymbol != null
&& arrayTypeRef != null
&& arrayTypeSymbol.Rank == arrayTypeRef.Rank
&& DoIsSameType(arrayTypeRef.ElementType, arrayTypeSymbol.ElementType);
}
// Optimistic approach
var declFullName = typeSymbol.ToString();
var typeRefFullName = typeRef.FullName;
if (typeRefFullName.Contains('`'))
{
typeRefFullName = s_genericArgCountRegex.Replace(typeRef.FullName, "");
}
if (declFullName == typeRefFullName)
{
return true;
}
// Built-in types - either top level or as generic arguments.
if (typeRef is GenericInstanceType genTypeRef)
{
if (!(typeSymbol is INamedTypeSymbol namedTypeSymbol) ||
!namedTypeSymbol.IsGenericType ||
genTypeRef.ElementType.Name != namedTypeSymbol.ConstructedFrom.MetadataName ||
genTypeRef.GenericArguments.Count != namedTypeSymbol.TypeArguments.Length ||
genTypeRef.ElementType.Namespace != namedTypeSymbol.ConstructedFrom.ContainingNamespace.ToString())
{
return false;
}
for (int i = 0; i < genTypeRef.GenericArguments.Count; ++i)
{
if (!DoIsSameType(genTypeRef.GenericArguments[i], namedTypeSymbol.TypeArguments[i]))
{
return false;
}
}
return true;
}
return
typeRef.Name == typeSymbol.Name &&
typeRef.IsBuiltInType() &&
typeSymbol.ContainingNamespace.Name == "System";
}
}
public static bool IsBuiltInType(this TypeReference t)
{
return t.Scope.Name == "mscorlib" && DoIsBuiltInType(t);
static bool DoIsBuiltInType(TypeReference t) => t switch
{
ArrayType arrayType => DoIsBuiltInType(arrayType.ElementType),
ByReferenceType byReferenceType => DoIsBuiltInType(byReferenceType.ElementType),
_ => t.IsPrimitive || t.Name == "Object" || t.Name == "Decimal" || t.Name == "String",
};
}
这篇关于如何将Roslyn语义模型返回的类型符号名称与Mono.Cecil返回的类型符号名称进行匹配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!