2009-08-30 11 views
8

私がこのお持ちの場合:私は、文字列として"System.Collections.Generic.Dictionary"取得するにはどうすればよい.NETでジェネリック型のベース名を取得する正しい方法は、サブストリングですか?

Type t = typeof(Dictionary<String, String>); 

を?これを行うための最善の方法です:

String n = t.FullName.Substring(0, t.FullName.IndexOf("`")); 

私はちょっとハックします。

私がこれを望む理由は、Typeオブジェクトを取得して、C#ソースコードファイルにあるコードに似たコードを生成したいからです。私はいくつかのテキストテンプレートを作成しています、と私はソースの中に文字列としてタイプを追加する必要がある、とFullNameプロパティは、このような生成します。代わりに私が何をしたいの

System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089]] 

System.Collections.Generic.Dictionary<System.String, System.String> 

編集は:[OK]を、ここでの最終的なコードは、だ、まだ私には少しハックのように思えるが、それは動作します:

/// <summary> 
/// This method takes a type and produces a proper full type name for it, expanding generics properly. 
/// </summary> 
/// <param name="type"> 
/// The type to produce the full type name for. 
/// </param> 
/// <returns> 
/// The type name for <paramref name="type"/> as a string. 
/// </returns> 
/// <exception cref="ArgumentNullException"> 
/// <para><paramref name="type"/> is <c>null</c>.</para> 
/// </exception> 
public static String TypeToString(Type type) 
{ 
    #region Parameter Validation 

    if (Object.ReferenceEquals(null, type)) 
     throw new ArgumentNullException("type"); 

    #endregion 

    if (type.IsGenericType) 
    { 
     if (type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
     { 
      Type underlyingType = type.GetGenericArguments()[0]; 
      return String.Format("{0}?", TypeToString(underlyingType)); 
     } 
     String baseName = type.FullName.Substring(0, type.FullName.IndexOf("`")); 
     return baseName + "<" + String.Join(", ", (from paramType in type.GetGenericArguments() 
                select TypeToString(paramType)).ToArray()) + ">"; 
    } 
    else 
    { 
     return type.FullName; 
    } 
} 

答えて

6

CodeDomを使用して、より「通常の」見栄えのC#スタイル宣言を生成できます。

System.Collections.Generic.Dictionary<string, int>  

任意のカスタム型文字列化コードなしで、あなたが何をしたいの大半を取得する必要があります:

CodeDomProvider csharpProvider = CodeDomProvider.CreateProvider("C#"); 
CodeTypeReference typeReference = new CodeTypeReference(typeof(Dictionary<string, int>)); 
CodeVariableDeclarationStatement variableDeclaration = new CodeVariableDeclarationStatement(typeReference, "dummy"); 
StringBuilder sb = new StringBuilder(); 
using (StringWriter writer = new StringWriter(sb)) 
{ 
    csharpProvider.GenerateCodeFromStatement(variableDeclaration, writer, new CodeGeneratorOptions()); 
} 

sb.Replace(" dummy;", null); 
Console.WriteLine(sb.ToString()); 

上記のコードは次のように出力されています。

2

AFAIKジェネリックの内部表記は、ジェネリック型への型パラメータの数を示すために `x表記法を使用します。私。 2は、辞書がそれを閉じるために2つのタイプを必要とすることを示します。 ILDasmとReflectionで使用されているのと同じ表記です。

+0

正しいが、私は示したように、サブストリングを使用して、汎用パーツ前に名前の一部を取得する唯一の方法であります、または私が知りませんプロパティやメソッドは、反射的な方法があるか? –

+0

JohannesHが彼の答えで指摘しているように、あなたが見るのはIL表記です。他のもの(C#のようなもの)が必要な場合は、自分でマップする必要があります。私たちはあなたが提案しているものに似た何かをする社内ツールをいくつか持っています。私はC#の構文を取得する他の方法を認識していませんが、一方で私はフォーマットが固​​定されていると仮定し、あなたはそれをあなた自身で安全に変換できるはずです。 –

7

問題は、言語固有の表記法(この場合はC#)が必要なことです。

​​

言語サービスを呼び出して必要な文字列を取得できますが、おそらく自分で文字列を生成する方がよいでしょう。

+0

さて、コードをそのまま残しておきます。 –

+0

MSDNのドキュメントでは、C#の構文(タイトルを除く)を使用しています。http://msdn.microsoft.com/en-us/library/xfhwa508.aspx –

+0

@Chris MSDNで使用していない表現を選択できますC#にする。 – JohannesH

3

これはあなたが探しているものに近いですか?

それはCodeTypeReferenceExpressionを使用し、任意の更なるSubstringReplace呼び出しを必要としない:

var type = typeof(Dictionary<string, string>); 
Console.WriteLine(TypeToString(type)); 

// ... 

public static string TypeToString(Type type) 
{ 
    if (type == null) throw new ArgumentNullException("type"); 

    var sb = new StringBuilder(); 
    using (var sw = new StringWriter(sb)) 
    { 
     var expr = new CodeTypeReferenceExpression(type); 

     var prov = new CSharpCodeProvider(); 
     prov.GenerateCodeFromExpression(expr, sw, new CodeGeneratorOptions()); 
    } 
    return sb.ToString(); 
} 
+0

@John:あなたはそうですが、この答えが間違っていることや、ダウンボートに値するというわけではありません。また、追加の文字列操作をせずにこれを行う方法については質問があり、Bobbymcrの答えには 'Replace'呼び出しが必要です。 – LukeH

関連する問題