如何获得Type的完整C#声明?

时间:2009-06-05 08:14:22

标签: c# .net reflection types

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

是否有一些内置的.Net方式来生成此声明?

举个例子,拿这个班:

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

当在typeof(Class1&lt;&gt; .Enum1)上调用函数(让我们称之为getCSharpDec)时,它将返回“My.Code.Here.Class1&lt;&gt; .Enum1”。

4 个答案:

答案 0 :(得分:5)

这里有几个问题......

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

作为一个未成年人,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;
    }
}

答案 1 :(得分:1)

Type.FullName正是您要找的。

答案 2 :(得分:1)

此代码适用于嵌套泛型类型(例如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);
    }
}

答案 3 :(得分:0)

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

之类的东西

请注意,正如Marc所指出的那样,如果你需要完全符合你指定的格式,这个名称可能就不是你想要的。