2009-06-05 79 views
1

我想寫一個函數來爲Type對象生成完整的C#聲明。我目前的方法涉及在Type對象上執行非常手動和特定的邏輯。如何獲得一個類型的完整的C#聲明?

是否有一些內置的.Net來生成這個聲明?

舉個例子,藉此類:

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

時功能(允許調用它getCSharpDec)調用的typeof(Class1的<> .Enum1),它將返回「My.Code.Here。 Class1 <> .Enum1「。

回答

5

有一對夫婦在這裏的問題...

  • C#和Type名的嵌套類型不同
  • C#和Type名泛型類型不同

作爲未成年人一邊,Class1<>.Enum1 ISN不是一個封閉的類型,但這不應該是一個問題...

(編輯)

這得到相當接近 - 它仍然從類型保留外仿製藥,雖然:

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; 
    } 
} 
+0

很好的例子,很多潛在的特殊情況。有一點需要注意,genArgs上的for循環可以用一個字符串替代.Join(「,」,genArgs.Select(x => x.FullName)。如果速度存在差異,我的猜測是Marcs代碼可能會更快,但是我個人比較喜歡循環的可讀性 – 2009-06-05 09:18:02

+0

,並使它們在功能上等同於選擇使用GetCSharpTypeName(T)而不是.FullName – 2009-06-05 09:18:54

1

你的意思是你想要的東西,如typeof(Class1<>.Enum1).FullName

請注意,儘管如Marc所示,如果您需要的格式完全符合您指定的格式,則此名稱可能並不完全符合您的要求。

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); 
    } 
}