如何将Roslyn语义模型返回的类型符号名称与Mono.Cecil返回的类型符号名称进行匹配? [英] How to match type symbol names as returned by Roslyn semantic model to those returned by Mono.Cecil?

查看:108
本文介绍了如何将Roslyn语义模型返回的类型符号名称与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆