代码之家  ›  专栏  ›  技术社区  ›  NoizWaves

如何获得类型的完整C声明?

  •  1
  • NoizWaves  · 技术社区  · 15 年前

    我正试图编写一个函数来为一个类型对象生成完整的C声明。我当前的方法涉及对类型对象执行非常手动和特定的逻辑。

    有没有一些到.NET的内置方法来生成此声明?

    以本课程为例:

    namespace My.Code.Here
    {
       public class Class1<>
       {
          public enum Enum1 { }
       }
    }
    

    当对typeof(class1<>.enum1)调用函数(让我们称之为get夏普dec)时,它将返回“my.code.here.class1<>.enum1”。

    4 回复  |  直到 15 年前
        1
  •  5
  •   Marc Gravell    15 年前

    这里有几个问题…

    • C和 Type 以不同的方式命名嵌套类型
    • C和 类型 以不同的方式命名泛型类型

    作为一个未成年人, Class1<>.Enum1 不是封闭式的,但这不应该是个问题…

    (编辑)

    这非常接近——它仍然保留了类型的外部泛型,不过:

    static void Main()
    {
        Type t = typeof(My.Code.Here.Class1<>.Enum1);
        string s = GetCSharpName(t); // My.Code.Here.Class1<T>.Enum1<T>
    }
    
    public static string GetCSharpName<T>()
    {
        return GetCSharpName(typeof(T));
    }
    public static string GetCSharpName(Type type)
    {
        StringBuilder sb = new StringBuilder();
        sb.Insert(0, GetCSharpTypeName(type));
        while (type.IsNested)
        {
            type = type.DeclaringType;
            sb.Insert(0, GetCSharpTypeName(type) + ".");
    
        }
        if(!string.IsNullOrEmpty(type.Namespace)) {
            sb.Insert(0, type.Namespace + ".");
        }
        return sb.ToString();
    }
    private static string GetCSharpTypeName(Type type)
    {
    
        if (type.IsGenericTypeDefinition || type.IsGenericType)
        {
            StringBuilder sb = new StringBuilder();
            int cut = type.Name.IndexOf('`');
            sb.Append(cut > 0 ? type.Name.Substring(0, cut) : type.Name);
    
            Type[] genArgs = type.GetGenericArguments();
            if (genArgs.Length > 0)
            {
                sb.Append('<');
                for (int i = 0; i < genArgs.Length; i++)
                {
                    sb.Append(GetCSharpTypeName(genArgs[i]));
                    if (i > 0) sb.Append(',');
                }
                sb.Append('>');
            }
            return sb.ToString();
        }
        else
        {
            return type.Name;
        }
    }
    
        2
  •  1
  •   Samuel Jack    15 年前

    Type.FullName 就是你要找的。

        3
  •  1
  •   Matthew Maddin    15 年前

    此代码应适用于嵌套的泛型类型(例如 Foo<int>.Bar<string,object> )

    public static string GetCSharpTypeName(this Type type, bool getFullName)
    {
        StringBuilder sb = new StringBuilder();
        if (getFullName && !string.IsNullOrEmpty(type.Namespace))
        {
            sb.Append(type.Namespace);
            sb.Append(".");
        }
        AppendCSharpTypeName(sb, type, getFullName);
        return sb.ToString();
    }
    
    private static void AppendCSharpTypeName
        (StringBuilder sb, Type type, bool fullParameterNames)
    {
        string typeName = type.Name;
        Type declaringType = type.DeclaringType;
    
        int declaringTypeArgumentCount = 0;
        if (type.IsNested)
        {
            if (declaringType.IsGenericTypeDefinition)
            {
                declaringTypeArgumentCount = 
                    declaringType.GetGenericArguments().Length;
                declaringType = declaringType.MakeGenericType(
                    type.GetGenericArguments().Take(declaringTypeArgumentCount)
                        .ToArray());
            }
    
            AppendCSharpTypeName(sb, declaringType, fullParameterNames);
            sb.Append(".");
        }
        Type[] genericArguments = type.GetGenericArguments()
            .Skip(declaringTypeArgumentCount).ToArray();
    
        int stopIndex;
        if ((type.IsGenericTypeDefinition || type.IsGenericType)
            && ((stopIndex = type.Name.IndexOf('`')) > 0))
        {
            sb.Append(typeName.Substring(0, stopIndex));
            string[] genericArgumentNames = genericArguments
                .Select(t => GetCSharpTypeName(t, fullParameterNames)).ToArray();
            if (genericArgumentNames.Length > 0)
                sb.AppendFormat("<{0}>", string.Join(",", genericArgumentNames));
        }
        else
        {
            sb.Append(typeName);
        }
    }
    
        4
  •  0
  •   jerryjvl    15 年前

    你是说你想要像 typeof(Class1<>.Enum1).FullName ?

    注意,尽管正如marc所指出的,如果您确实需要指定的格式,那么这个名称可能并不完全是您想要的。